aboutsummaryrefslogtreecommitdiff
path: root/quantum/rgblight.c
diff options
context:
space:
mode:
authorNathan Gray <n8gray@n8gray.org>2020-03-10 12:50:01 -0700
committerGitHub <noreply@github.com>2020-03-10 12:50:01 -0700
commit2ffb08843ba59f0af0870335934bdb277fc85620 (patch)
treef38f760dd73bca0f7089ff8751eecc03a95f7256 /quantum/rgblight.c
parent2a8ccafe6e704eced2d383810e1061613871433e (diff)
downloadqmk_firmware-2ffb08843ba59f0af0870335934bdb277fc85620.tar.gz
qmk_firmware-2ffb08843ba59f0af0870335934bdb277fc85620.zip
Feature: RGBLight layers (#7768)
* New feature: RGBLIGHT_LAYERS This feature allows users to define multiple independent layers of lighting that can be toggled on and off individually, making it easy to use your RGB lighting to indicate things like active keyboard layer & modifier state. * Demonstrate built in functions for layer state checking Also link the video in the docs. * Follow existing pattern for setting rgblight_status flags * Eliminate rgblight_is_static_mode since it's not needed Just check to see if the timer is enabled directly.
Diffstat (limited to 'quantum/rgblight.c')
-rw-r--r--quantum/rgblight.c71
1 files changed, 71 insertions, 0 deletions
diff --git a/quantum/rgblight.c b/quantum/rgblight.c
index f072ae8ca..b3f0f18d4 100644
--- a/quantum/rgblight.c
+++ b/quantum/rgblight.c
@@ -38,17 +38,23 @@
38# include "velocikey.h" 38# include "velocikey.h"
39#endif 39#endif
40 40
41#ifndef MIN
42# define MIN(a, b) (((a) < (b)) ? (a) : (b))
43#endif
44
41#ifdef RGBLIGHT_SPLIT 45#ifdef RGBLIGHT_SPLIT
42/* for split keyboard */ 46/* for split keyboard */
43# define RGBLIGHT_SPLIT_SET_CHANGE_MODE rgblight_status.change_flags |= RGBLIGHT_STATUS_CHANGE_MODE 47# define RGBLIGHT_SPLIT_SET_CHANGE_MODE rgblight_status.change_flags |= RGBLIGHT_STATUS_CHANGE_MODE
44# define RGBLIGHT_SPLIT_SET_CHANGE_HSVS rgblight_status.change_flags |= RGBLIGHT_STATUS_CHANGE_HSVS 48# define RGBLIGHT_SPLIT_SET_CHANGE_HSVS rgblight_status.change_flags |= RGBLIGHT_STATUS_CHANGE_HSVS
45# define RGBLIGHT_SPLIT_SET_CHANGE_MODEHSVS rgblight_status.change_flags |= (RGBLIGHT_STATUS_CHANGE_MODE | RGBLIGHT_STATUS_CHANGE_HSVS) 49# define RGBLIGHT_SPLIT_SET_CHANGE_MODEHSVS rgblight_status.change_flags |= (RGBLIGHT_STATUS_CHANGE_MODE | RGBLIGHT_STATUS_CHANGE_HSVS)
50# define RGBLIGHT_SPLIT_SET_CHANGE_LAYERS rgblight_status.change_flags |= RGBLIGHT_STATUS_CHANGE_LAYERS
46# define RGBLIGHT_SPLIT_SET_CHANGE_TIMER_ENABLE rgblight_status.change_flags |= RGBLIGHT_STATUS_CHANGE_TIMER 51# define RGBLIGHT_SPLIT_SET_CHANGE_TIMER_ENABLE rgblight_status.change_flags |= RGBLIGHT_STATUS_CHANGE_TIMER
47# define RGBLIGHT_SPLIT_ANIMATION_TICK rgblight_status.change_flags |= RGBLIGHT_STATUS_ANIMATION_TICK 52# define RGBLIGHT_SPLIT_ANIMATION_TICK rgblight_status.change_flags |= RGBLIGHT_STATUS_ANIMATION_TICK
48#else 53#else
49# define RGBLIGHT_SPLIT_SET_CHANGE_MODE 54# define RGBLIGHT_SPLIT_SET_CHANGE_MODE
50# define RGBLIGHT_SPLIT_SET_CHANGE_HSVS 55# define RGBLIGHT_SPLIT_SET_CHANGE_HSVS
51# define RGBLIGHT_SPLIT_SET_CHANGE_MODEHSVS 56# define RGBLIGHT_SPLIT_SET_CHANGE_MODEHSVS
57# define RGBLIGHT_SPLIT_SET_CHANGE_LAYERS
52# define RGBLIGHT_SPLIT_SET_CHANGE_TIMER_ENABLE 58# define RGBLIGHT_SPLIT_SET_CHANGE_TIMER_ENABLE
53# define RGBLIGHT_SPLIT_ANIMATION_TICK 59# define RGBLIGHT_SPLIT_ANIMATION_TICK
54#endif 60#endif
@@ -97,6 +103,10 @@ LED_TYPE led[RGBLED_NUM];
97# define LED_ARRAY led 103# define LED_ARRAY led
98#endif 104#endif
99 105
106#ifdef RGBLIGHT_LAYERS
107rgblight_segment_t const * const *rgblight_layers = NULL;
108#endif
109
100static uint8_t clipping_start_pos = 0; 110static uint8_t clipping_start_pos = 0;
101static uint8_t clipping_num_leds = RGBLED_NUM; 111static uint8_t clipping_num_leds = RGBLED_NUM;
102static uint8_t effect_start_pos = 0; 112static uint8_t effect_start_pos = 0;
@@ -604,11 +614,67 @@ void rgblight_sethsv_master(uint8_t hue, uint8_t sat, uint8_t val) { rgblight_se
604void rgblight_sethsv_slave(uint8_t hue, uint8_t sat, uint8_t val) { rgblight_sethsv_range(hue, sat, val, (uint8_t)RGBLED_NUM / 2, (uint8_t)RGBLED_NUM); } 614void rgblight_sethsv_slave(uint8_t hue, uint8_t sat, uint8_t val) { rgblight_sethsv_range(hue, sat, val, (uint8_t)RGBLED_NUM / 2, (uint8_t)RGBLED_NUM); }
605#endif // ifndef RGBLIGHT_SPLIT 615#endif // ifndef RGBLIGHT_SPLIT
606 616
617#ifdef RGBLIGHT_LAYERS
618void rgblight_set_layer_state(uint8_t layer, bool enabled) {
619 uint8_t mask = 1 << layer;
620 if (enabled) {
621 rgblight_status.enabled_layer_mask |= mask;
622 } else {
623 rgblight_status.enabled_layer_mask &= ~mask;
624 }
625 RGBLIGHT_SPLIT_SET_CHANGE_LAYERS;
626 // Static modes don't have a ticker running to update the LEDs
627 if (rgblight_status.timer_enabled == false) {
628 rgblight_mode_noeeprom(rgblight_config.mode);
629 }
630}
631
632bool rgblight_get_layer_state(uint8_t layer) {
633 uint8_t mask = 1 << layer;
634 return (rgblight_status.enabled_layer_mask & mask) != 0;
635}
636
637// Write any enabled LED layers into the buffer
638static void rgblight_layers_write(void) {
639 uint8_t i = 0;
640 // For each layer
641 for (const rgblight_segment_t * const *layer_ptr = rgblight_layers; i < RGBLIGHT_MAX_LAYERS; layer_ptr++, i++) {
642 if (!rgblight_get_layer_state(i)) {
643 continue; // Layer is disabled
644 }
645 const rgblight_segment_t * segment_ptr = pgm_read_ptr(layer_ptr);
646 if (segment_ptr == NULL) {
647 break; // No more layers
648 }
649 // For each segment
650 while (1) {
651 rgblight_segment_t segment;
652 memcpy_P(&segment, segment_ptr, sizeof(rgblight_segment_t));
653 if (segment.index == RGBLIGHT_END_SEGMENT_INDEX) {
654 break; // No more segments
655 }
656 // Write segment.count LEDs
657 LED_TYPE * const limit = &led[MIN(segment.index + segment.count, RGBLED_NUM)];
658 for (LED_TYPE *led_ptr = &led[segment.index]; led_ptr < limit; led_ptr++) {
659 sethsv(segment.hue, segment.sat, segment.val, led_ptr);
660 }
661 segment_ptr++;
662 }
663 }
664}
665#endif
666
607#ifndef RGBLIGHT_CUSTOM_DRIVER 667#ifndef RGBLIGHT_CUSTOM_DRIVER
608void rgblight_set(void) { 668void rgblight_set(void) {
609 LED_TYPE *start_led; 669 LED_TYPE *start_led;
610 uint16_t num_leds = clipping_num_leds; 670 uint16_t num_leds = clipping_num_leds;
611 671
672# ifdef RGBLIGHT_LAYERS
673 if (rgblight_layers != NULL) {
674 rgblight_layers_write();
675 }
676# endif
677
612 if (!rgblight_config.enable) { 678 if (!rgblight_config.enable) {
613 for (uint8_t i = effect_start_pos; i < effect_end_pos; i++) { 679 for (uint8_t i = effect_start_pos; i < effect_end_pos; i++) {
614 led[i].r = 0; 680 led[i].r = 0;
@@ -652,6 +718,11 @@ void rgblight_get_syncinfo(rgblight_syncinfo_t *syncinfo) {
652 718
653/* for split keyboard slave side */ 719/* for split keyboard slave side */
654void rgblight_update_sync(rgblight_syncinfo_t *syncinfo, bool write_to_eeprom) { 720void rgblight_update_sync(rgblight_syncinfo_t *syncinfo, bool write_to_eeprom) {
721# ifdef RGBLIGHT_LAYERS
722 if (syncinfo->status.change_flags & RGBLIGHT_STATUS_CHANGE_LAYERS) {
723 rgblight_status.enabled_layer_mask = syncinfo->status.enabled_layer_mask;
724 }
725# endif
655 if (syncinfo->status.change_flags & RGBLIGHT_STATUS_CHANGE_MODE) { 726 if (syncinfo->status.change_flags & RGBLIGHT_STATUS_CHANGE_MODE) {
656 if (syncinfo->config.enable) { 727 if (syncinfo->config.enable) {
657 rgblight_config.enable = 1; // == rgblight_enable_noeeprom(); 728 rgblight_config.enable = 1; // == rgblight_enable_noeeprom();