aboutsummaryrefslogtreecommitdiff
path: root/keyboards/mxss/rgblight.c
diff options
context:
space:
mode:
Diffstat (limited to 'keyboards/mxss/rgblight.c')
-rw-r--r--keyboards/mxss/rgblight.c382
1 files changed, 289 insertions, 93 deletions
diff --git a/keyboards/mxss/rgblight.c b/keyboards/mxss/rgblight.c
index 2e9352c55..d2d79815c 100644
--- a/keyboards/mxss/rgblight.c
+++ b/keyboards/mxss/rgblight.c
@@ -15,13 +15,16 @@
15 */ 15 */
16#include <math.h> 16#include <math.h>
17#include <string.h> 17#include <string.h>
18#include <stdlib.h>
18#ifdef __AVR__ 19#ifdef __AVR__
19# include <avr/eeprom.h> 20# include <avr/eeprom.h>
20# include <avr/interrupt.h> 21# include <avr/interrupt.h>
21#endif 22#endif
23#ifdef EEPROM_ENABLE
24# include "eeprom.h"
25#endif
22#ifdef STM32_EEPROM_ENABLE 26#ifdef STM32_EEPROM_ENABLE
23# include <hal.h> 27# include <hal.h>
24# include "eeprom.h"
25# include "eeprom_stm32.h" 28# include "eeprom_stm32.h"
26#endif 29#endif
27#include "wait.h" 30#include "wait.h"
@@ -38,17 +41,23 @@
38// MxSS custom 41// MxSS custom
39#include "mxss_frontled.h" 42#include "mxss_frontled.h"
40 43
44#ifndef MIN
45# define MIN(a, b) (((a) < (b)) ? (a) : (b))
46#endif
47
41#ifdef RGBLIGHT_SPLIT 48#ifdef RGBLIGHT_SPLIT
42/* for split keyboard */ 49/* for split keyboard */
43# define RGBLIGHT_SPLIT_SET_CHANGE_MODE rgblight_status.change_flags |= RGBLIGHT_STATUS_CHANGE_MODE 50# 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 51# 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) 52# define RGBLIGHT_SPLIT_SET_CHANGE_MODEHSVS rgblight_status.change_flags |= (RGBLIGHT_STATUS_CHANGE_MODE | RGBLIGHT_STATUS_CHANGE_HSVS)
53# 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 54# 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 55# define RGBLIGHT_SPLIT_ANIMATION_TICK rgblight_status.change_flags |= RGBLIGHT_STATUS_ANIMATION_TICK
48#else 56#else
49# define RGBLIGHT_SPLIT_SET_CHANGE_MODE 57# define RGBLIGHT_SPLIT_SET_CHANGE_MODE
50# define RGBLIGHT_SPLIT_SET_CHANGE_HSVS 58# define RGBLIGHT_SPLIT_SET_CHANGE_HSVS
51# define RGBLIGHT_SPLIT_SET_CHANGE_MODEHSVS 59# define RGBLIGHT_SPLIT_SET_CHANGE_MODEHSVS
60# define RGBLIGHT_SPLIT_SET_CHANGE_LAYERS
52# define RGBLIGHT_SPLIT_SET_CHANGE_TIMER_ENABLE 61# define RGBLIGHT_SPLIT_SET_CHANGE_TIMER_ENABLE
53# define RGBLIGHT_SPLIT_ANIMATION_TICK 62# define RGBLIGHT_SPLIT_ANIMATION_TICK
54#endif 63#endif
@@ -97,11 +106,11 @@ LED_TYPE led[RGBLED_NUM];
97# define LED_ARRAY led 106# define LED_ARRAY led
98#endif 107#endif
99 108
100static uint8_t clipping_start_pos = 0; 109#ifdef RGBLIGHT_LAYERS
101static uint8_t clipping_num_leds = RGBLED_NUM; 110rgblight_segment_t const *const *rgblight_layers = NULL;
102static uint8_t effect_start_pos = 0; 111#endif
103static uint8_t effect_end_pos = RGBLED_NUM; 112
104static uint8_t effect_num_leds = RGBLED_NUM; 113rgblight_ranges_t rgblight_ranges = {0, RGBLED_NUM, 0, RGBLED_NUM, RGBLED_NUM};
105 114
106// MxSS custom 115// MxSS custom
107extern uint8_t fled_mode; 116extern uint8_t fled_mode;
@@ -116,18 +125,20 @@ void copyrgb(LED_TYPE *src, LED_TYPE *dst) {
116} 125}
117 126
118void rgblight_set_clipping_range(uint8_t start_pos, uint8_t num_leds) { 127void rgblight_set_clipping_range(uint8_t start_pos, uint8_t num_leds) {
119 clipping_start_pos = start_pos; 128 rgblight_ranges.clipping_start_pos = start_pos;
120 clipping_num_leds = num_leds; 129 rgblight_ranges.clipping_num_leds = num_leds;
121} 130}
122 131
123void rgblight_set_effect_range(uint8_t start_pos, uint8_t num_leds) { 132void rgblight_set_effect_range(uint8_t start_pos, uint8_t num_leds) {
124 if (start_pos >= RGBLED_NUM) return; 133 if (start_pos >= RGBLED_NUM) return;
125 if (start_pos + num_leds > RGBLED_NUM) return; 134 if (start_pos + num_leds > RGBLED_NUM) return;
126 effect_start_pos = start_pos; 135 rgblight_ranges.effect_start_pos = start_pos;
127 effect_end_pos = start_pos + num_leds; 136 rgblight_ranges.effect_end_pos = start_pos + num_leds;
128 effect_num_leds = num_leds; 137 rgblight_ranges.effect_num_leds = num_leds;
129} 138}
130 139
140__attribute__((weak)) RGB rgblight_hsv_to_rgb(HSV hsv) { return hsv_to_rgb(hsv); }
141
131void sethsv_raw(uint8_t hue, uint8_t sat, uint8_t val, LED_TYPE *led1) { 142void sethsv_raw(uint8_t hue, uint8_t sat, uint8_t val, LED_TYPE *led1) {
132 HSV hsv = {hue, sat, val}; 143 HSV hsv = {hue, sat, val};
133 // MxSS custom 144 // MxSS custom
@@ -138,7 +149,8 @@ void sethsv_raw(uint8_t hue, uint8_t sat, uint8_t val, LED_TYPE *led1) {
138 } else if (led1 == &led[RGBLIGHT_FLED2]) { 149 } else if (led1 == &led[RGBLIGHT_FLED2]) {
139 fled_hs[1].hue = hue; 150 fled_hs[1].hue = hue;
140 fled_hs[1].sat = sat; 151 fled_hs[1].sat = sat;
141 } RGB rgb = hsv_to_rgb(hsv); 152 }
153 RGB rgb = rgblight_hsv_to_rgb(hsv);
142 setrgb(rgb.r, rgb.g, rgb.b, led1); 154 setrgb(rgb.r, rgb.g, rgb.b, led1);
143} 155}
144 156
@@ -168,7 +180,7 @@ void rgblight_check_config(void) {
168} 180}
169 181
170uint32_t eeconfig_read_rgblight(void) { 182uint32_t eeconfig_read_rgblight(void) {
171#if defined(__AVR__) || defined(STM32_EEPROM_ENABLE) || defined(PROTOCOL_ARM_ATSAM) || defined(EEPROM_SIZE) 183#ifdef EEPROM_ENABLE
172 return eeprom_read_dword(EECONFIG_RGBLIGHT); 184 return eeprom_read_dword(EECONFIG_RGBLIGHT);
173#else 185#else
174 return 0; 186 return 0;
@@ -176,15 +188,13 @@ uint32_t eeconfig_read_rgblight(void) {
176} 188}
177 189
178void eeconfig_update_rgblight(uint32_t val) { 190void eeconfig_update_rgblight(uint32_t val) {
179#if defined(__AVR__) || defined(STM32_EEPROM_ENABLE) || defined(PROTOCOL_ARM_ATSAM) || defined(EEPROM_SIZE) 191#ifdef EEPROM_ENABLE
180 rgblight_check_config(); 192 rgblight_check_config();
181 eeprom_update_dword(EECONFIG_RGBLIGHT, val); 193 eeprom_update_dword(EECONFIG_RGBLIGHT, val);
182#endif 194#endif
183} 195}
184 196
185void eeconfig_update_rgblight_current(void) { 197void eeconfig_update_rgblight_current(void) { eeconfig_update_rgblight(rgblight_config.raw); }
186 eeconfig_update_rgblight(rgblight_config.raw);
187}
188 198
189void eeconfig_update_rgblight_default(void) { 199void eeconfig_update_rgblight_default(void) {
190 rgblight_config.enable = 1; 200 rgblight_config.enable = 1;
@@ -233,9 +243,7 @@ void rgblight_init(void) {
233 243
234 eeconfig_debug_rgblight(); // display current eeprom values 244 eeconfig_debug_rgblight(); // display current eeprom values
235 245
236#ifdef RGBLIGHT_USE_TIMER
237 rgblight_timer_init(); // setup the timer 246 rgblight_timer_init(); // setup the timer
238#endif
239 247
240 if (rgblight_config.enable) { 248 if (rgblight_config.enable) {
241 rgblight_mode_noeeprom(rgblight_config.mode); 249 rgblight_mode_noeeprom(rgblight_config.mode);
@@ -252,9 +260,7 @@ void rgblight_update_dword(uint32_t dword) {
252 if (rgblight_config.enable) 260 if (rgblight_config.enable)
253 rgblight_mode_noeeprom(rgblight_config.mode); 261 rgblight_mode_noeeprom(rgblight_config.mode);
254 else { 262 else {
255#ifdef RGBLIGHT_USE_TIMER
256 rgblight_timer_disable(); 263 rgblight_timer_disable();
257#endif
258 rgblight_set(); 264 rgblight_set();
259 } 265 }
260} 266}
@@ -322,13 +328,9 @@ void rgblight_mode_eeprom_helper(uint8_t mode, bool write_to_eeprom) {
322 dprintf("rgblight mode [NOEEPROM]: %u\n", rgblight_config.mode); 328 dprintf("rgblight mode [NOEEPROM]: %u\n", rgblight_config.mode);
323 } 329 }
324 if (is_static_effect(rgblight_config.mode)) { 330 if (is_static_effect(rgblight_config.mode)) {
325#ifdef RGBLIGHT_USE_TIMER
326 rgblight_timer_disable(); 331 rgblight_timer_disable();
327#endif
328 } else { 332 } else {
329#ifdef RGBLIGHT_USE_TIMER
330 rgblight_timer_enable(); 333 rgblight_timer_enable();
331#endif
332 } 334 }
333#ifdef RGBLIGHT_USE_TIMER 335#ifdef RGBLIGHT_USE_TIMER
334 animation_status.restart = true; 336 animation_status.restart = true;
@@ -376,9 +378,7 @@ void rgblight_disable(void) {
376 rgblight_config.enable = 0; 378 rgblight_config.enable = 0;
377 eeconfig_update_rgblight(rgblight_config.raw); 379 eeconfig_update_rgblight(rgblight_config.raw);
378 dprintf("rgblight disable [EEPROM]: rgblight_config.enable = %u\n", rgblight_config.enable); 380 dprintf("rgblight disable [EEPROM]: rgblight_config.enable = %u\n", rgblight_config.enable);
379#ifdef RGBLIGHT_USE_TIMER
380 rgblight_timer_disable(); 381 rgblight_timer_disable();
381#endif
382 RGBLIGHT_SPLIT_SET_CHANGE_MODE; 382 RGBLIGHT_SPLIT_SET_CHANGE_MODE;
383 wait_ms(50); 383 wait_ms(50);
384 rgblight_set(); 384 rgblight_set();
@@ -387,14 +387,14 @@ void rgblight_disable(void) {
387void rgblight_disable_noeeprom(void) { 387void rgblight_disable_noeeprom(void) {
388 rgblight_config.enable = 0; 388 rgblight_config.enable = 0;
389 dprintf("rgblight disable [NOEEPROM]: rgblight_config.enable = %u\n", rgblight_config.enable); 389 dprintf("rgblight disable [NOEEPROM]: rgblight_config.enable = %u\n", rgblight_config.enable);
390#ifdef RGBLIGHT_USE_TIMER
391 rgblight_timer_disable(); 390 rgblight_timer_disable();
392#endif
393 RGBLIGHT_SPLIT_SET_CHANGE_MODE; 391 RGBLIGHT_SPLIT_SET_CHANGE_MODE;
394 wait_ms(50); 392 wait_ms(50);
395 rgblight_set(); 393 rgblight_set();
396} 394}
397 395
396bool rgblight_is_enabled(void) { return rgblight_config.enable; }
397
398void rgblight_increase_hue_helper(bool write_to_eeprom) { 398void rgblight_increase_hue_helper(bool write_to_eeprom) {
399 uint8_t hue = rgblight_config.hue + RGBLIGHT_HUE_STEP; 399 uint8_t hue = rgblight_config.hue + RGBLIGHT_HUE_STEP;
400 rgblight_sethsv_eeprom_helper(hue, rgblight_config.sat, rgblight_config.val, write_to_eeprom); 400 rgblight_sethsv_eeprom_helper(hue, rgblight_config.sat, rgblight_config.val, write_to_eeprom);
@@ -431,17 +431,25 @@ void rgblight_decrease_val_helper(bool write_to_eeprom) {
431} 431}
432void rgblight_decrease_val_noeeprom(void) { rgblight_decrease_val_helper(false); } 432void rgblight_decrease_val_noeeprom(void) { rgblight_decrease_val_helper(false); }
433void rgblight_decrease_val(void) { rgblight_decrease_val_helper(true); } 433void rgblight_decrease_val(void) { rgblight_decrease_val_helper(true); }
434void rgblight_increase_speed(void) { 434
435void rgblight_increase_speed_helper(bool write_to_eeprom) {
435 if (rgblight_config.speed < 3) rgblight_config.speed++; 436 if (rgblight_config.speed < 3) rgblight_config.speed++;
436 // RGBLIGHT_SPLIT_SET_CHANGE_HSVS; // NEED? 437 // RGBLIGHT_SPLIT_SET_CHANGE_HSVS; // NEED?
437 eeconfig_update_rgblight(rgblight_config.raw); // EECONFIG needs to be increased to support this 438 if (write_to_eeprom) {
439 eeconfig_update_rgblight(rgblight_config.raw); // EECONFIG needs to be increased to support this
440 }
438} 441}
439 442void rgblight_increase_speed(void) { rgblight_increase_speed_helper(true); }
440void rgblight_decrease_speed(void) { 443void rgblight_increase_speed_noeeprom(void) { rgblight_increase_speed_helper(false); }
444void rgblight_decrease_speed_helper(bool write_to_eeprom) {
441 if (rgblight_config.speed > 0) rgblight_config.speed--; 445 if (rgblight_config.speed > 0) rgblight_config.speed--;
442 // RGBLIGHT_SPLIT_SET_CHANGE_HSVS; // NEED?? 446 // RGBLIGHT_SPLIT_SET_CHANGE_HSVS; // NEED??
443 eeconfig_update_rgblight(rgblight_config.raw); // EECONFIG needs to be increased to support this 447 if (write_to_eeprom) {
448 eeconfig_update_rgblight(rgblight_config.raw); // EECONFIG needs to be increased to support this
449 }
444} 450}
451void rgblight_decrease_speed(void) { rgblight_decrease_speed_helper(true); }
452void rgblight_decrease_speed_noeeprom(void) { rgblight_decrease_speed_helper(false); }
445 453
446void rgblight_sethsv_noeeprom_old(uint8_t hue, uint8_t sat, uint8_t val) { 454void rgblight_sethsv_noeeprom_old(uint8_t hue, uint8_t sat, uint8_t val) {
447 if (rgblight_config.enable) { 455 if (rgblight_config.enable) {
@@ -502,15 +510,15 @@ void rgblight_sethsv_eeprom_helper(uint8_t hue, uint8_t sat, uint8_t val, bool w
502# else 510# else
503 uint8_t range = RGBLED_GRADIENT_RANGES[delta / 2]; 511 uint8_t range = RGBLED_GRADIENT_RANGES[delta / 2];
504# endif 512# endif
505 for (uint8_t i = 0; i < effect_num_leds; i++) { 513 for (uint8_t i = 0; i < rgblight_ranges.effect_num_leds; i++) {
506 uint8_t _hue = ((uint16_t)i * (uint16_t)range) / effect_num_leds; 514 uint8_t _hue = ((uint16_t)i * (uint16_t)range) / rgblight_ranges.effect_num_leds;
507 if (direction) { 515 if (direction) {
508 _hue = hue + _hue; 516 _hue = hue + _hue;
509 } else { 517 } else {
510 _hue = hue - _hue; 518 _hue = hue - _hue;
511 } 519 }
512 dprintf("rgblight rainbow set hsv: %d,%d,%d,%u\n", i, _hue, direction, range); 520 dprintf("rgblight rainbow set hsv: %d,%d,%d,%u\n", i, _hue, direction, range);
513 sethsv(_hue, sat, val, (LED_TYPE *)&led[i + effect_start_pos]); 521 sethsv(_hue, sat, val, (LED_TYPE *)&led[i + rgblight_ranges.effect_start_pos]);
514 } 522 }
515 rgblight_set(); 523 rgblight_set();
516 } 524 }
@@ -542,7 +550,7 @@ uint8_t rgblight_get_speed(void) { return rgblight_config.speed; }
542void rgblight_set_speed_eeprom_helper(uint8_t speed, bool write_to_eeprom) { 550void rgblight_set_speed_eeprom_helper(uint8_t speed, bool write_to_eeprom) {
543 rgblight_config.speed = speed; 551 rgblight_config.speed = speed;
544 if (write_to_eeprom) { 552 if (write_to_eeprom) {
545 eeconfig_update_rgblight(rgblight_config.raw); // EECONFIG needs to be increased to support this 553 eeconfig_update_rgblight(rgblight_config.raw); // EECONFIG needs to be increased to support this
546 dprintf("rgblight set speed [EEPROM]: %u\n", rgblight_config.speed); 554 dprintf("rgblight set speed [EEPROM]: %u\n", rgblight_config.speed);
547 } else { 555 } else {
548 dprintf("rgblight set speed [NOEEPROM]: %u\n", rgblight_config.speed); 556 dprintf("rgblight set speed [NOEEPROM]: %u\n", rgblight_config.speed);
@@ -559,12 +567,14 @@ uint8_t rgblight_get_sat(void) { return rgblight_config.sat; }
559 567
560uint8_t rgblight_get_val(void) { return rgblight_config.val; } 568uint8_t rgblight_get_val(void) { return rgblight_config.val; }
561 569
570HSV rgblight_get_hsv(void) { return (HSV){rgblight_config.hue, rgblight_config.sat, rgblight_config.val}; }
571
562void rgblight_setrgb(uint8_t r, uint8_t g, uint8_t b) { 572void rgblight_setrgb(uint8_t r, uint8_t g, uint8_t b) {
563 if (!rgblight_config.enable) { 573 if (!rgblight_config.enable) {
564 return; 574 return;
565 } 575 }
566 576
567 for (uint8_t i = effect_start_pos; i < effect_end_pos; i++) { 577 for (uint8_t i = rgblight_ranges.effect_start_pos; i < rgblight_ranges.effect_end_pos; i++) {
568 led[i].r = r; 578 led[i].r = r;
569 led[i].g = g; 579 led[i].g = g;
570 led[i].b = b; 580 led[i].b = b;
@@ -599,7 +609,7 @@ void rgblight_sethsv_at(uint8_t hue, uint8_t sat, uint8_t val, uint8_t index) {
599 rgblight_setrgb_at(tmp_led.r, tmp_led.g, tmp_led.b, index); 609 rgblight_setrgb_at(tmp_led.r, tmp_led.g, tmp_led.b, index);
600} 610}
601 611
602#if defined(RGBLIGHT_EFFECT_BREATHING) || defined(RGBLIGHT_EFFECT_RAINBOW_MOOD) || defined(RGBLIGHT_EFFECT_RAINBOW_SWIRL) || defined(RGBLIGHT_EFFECT_SNAKE) || defined(RGBLIGHT_EFFECT_KNIGHT) 612#if defined(RGBLIGHT_EFFECT_BREATHING) || defined(RGBLIGHT_EFFECT_RAINBOW_MOOD) || defined(RGBLIGHT_EFFECT_RAINBOW_SWIRL) || defined(RGBLIGHT_EFFECT_SNAKE) || defined(RGBLIGHT_EFFECT_KNIGHT) || defined(RGBLIGHT_EFFECT_TWINKLE)
603 613
604static uint8_t get_interval_time(const uint8_t *default_interval_address, uint8_t velocikey_min, uint8_t velocikey_max) { 614static uint8_t get_interval_time(const uint8_t *default_interval_address, uint8_t velocikey_min, uint8_t velocikey_max) {
605 return 615 return
@@ -648,13 +658,97 @@ void rgblight_sethsv_master(uint8_t hue, uint8_t sat, uint8_t val) { rgblight_se
648void 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); } 658void 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); }
649#endif // ifndef RGBLIGHT_SPLIT 659#endif // ifndef RGBLIGHT_SPLIT
650 660
661#ifdef RGBLIGHT_LAYERS
662void rgblight_set_layer_state(uint8_t layer, bool enabled) {
663 rgblight_layer_mask_t mask = 1 << layer;
664 if (enabled) {
665 rgblight_status.enabled_layer_mask |= mask;
666 } else {
667 rgblight_status.enabled_layer_mask &= ~mask;
668 }
669 RGBLIGHT_SPLIT_SET_CHANGE_LAYERS;
670 // Static modes don't have a ticker running to update the LEDs
671 if (rgblight_status.timer_enabled == false) {
672 rgblight_mode_noeeprom(rgblight_config.mode);
673 }
674
675# ifdef RGBLIGHT_LAYERS_OVERRIDE_RGB_OFF
676 // If not enabled, then nothing else will actually set the LEDs...
677 if (!rgblight_config.enable) {
678 rgblight_set();
679 }
680# endif
681}
682
683bool rgblight_get_layer_state(uint8_t layer) {
684 rgblight_layer_mask_t mask = 1 << layer;
685 return (rgblight_status.enabled_layer_mask & mask) != 0;
686}
687
688// Write any enabled LED layers into the buffer
689static void rgblight_layers_write(void) {
690 uint8_t i = 0;
691 // For each layer
692 for (const rgblight_segment_t *const *layer_ptr = rgblight_layers; i < RGBLIGHT_MAX_LAYERS; layer_ptr++, i++) {
693 if (!rgblight_get_layer_state(i)) {
694 continue; // Layer is disabled
695 }
696 const rgblight_segment_t *segment_ptr = pgm_read_ptr(layer_ptr);
697 if (segment_ptr == NULL) {
698 break; // No more layers
699 }
700 // For each segment
701 while (1) {
702 rgblight_segment_t segment;
703 memcpy_P(&segment, segment_ptr, sizeof(rgblight_segment_t));
704 if (segment.index == RGBLIGHT_END_SEGMENT_INDEX) {
705 break; // No more segments
706 }
707 // Write segment.count LEDs
708 LED_TYPE *const limit = &led[MIN(segment.index + segment.count, RGBLED_NUM)];
709 for (LED_TYPE *led_ptr = &led[segment.index]; led_ptr < limit; led_ptr++) {
710 sethsv(segment.hue, segment.sat, segment.val, led_ptr);
711 }
712 segment_ptr++;
713 }
714 }
715}
716
717# ifdef RGBLIGHT_LAYER_BLINK
718rgblight_layer_mask_t _blinked_layer_mask = 0;
719uint16_t _blink_duration = 0;
720static uint16_t _blink_timer;
721
722void rgblight_blink_layer(uint8_t layer, uint16_t duration_ms) {
723 rgblight_set_layer_state(layer, true);
724 _blinked_layer_mask |= 1 << layer;
725 _blink_timer = timer_read();
726 _blink_duration = duration_ms;
727}
728
729void rgblight_unblink_layers(void) {
730 if (_blinked_layer_mask != 0 && timer_elapsed(_blink_timer) > _blink_duration) {
731 for (uint8_t layer = 0; layer < RGBLIGHT_MAX_LAYERS; layer++) {
732 if ((_blinked_layer_mask & 1 << layer) != 0) {
733 rgblight_set_layer_state(layer, false);
734 }
735 }
736 _blinked_layer_mask = 0;
737 }
738}
739# endif
740
741#endif
742
743__attribute__((weak)) void rgblight_call_driver(LED_TYPE *start_led, uint8_t num_leds) { ws2812_setleds(start_led, num_leds); }
744
651#ifndef RGBLIGHT_CUSTOM_DRIVER 745#ifndef RGBLIGHT_CUSTOM_DRIVER
652void rgblight_set(void) { 746void rgblight_set(void) {
653 LED_TYPE *start_led; 747 LED_TYPE *start_led;
654 uint16_t num_leds = clipping_num_leds; 748 uint8_t num_leds = rgblight_ranges.clipping_num_leds;
655 749
656 if (!rgblight_config.enable) { 750 if (!rgblight_config.enable) {
657 for (uint8_t i = effect_start_pos; i < effect_end_pos; i++) { 751 for (uint8_t i = rgblight_ranges.effect_start_pos; i < rgblight_ranges.effect_end_pos; i++) {
658 if (i == RGBLIGHT_FLED1 && i == RGBLIGHT_FLED2) 752 if (i == RGBLIGHT_FLED1 && i == RGBLIGHT_FLED2)
659 continue; 753 continue;
660 754
@@ -667,54 +761,63 @@ void rgblight_set(void) {
667 } 761 }
668 } 762 }
669 763
764# ifdef RGBLIGHT_LAYERS
765 if (rgblight_layers != NULL
766# ifndef RGBLIGHT_LAYERS_OVERRIDE_RGB_OFF
767 && rgblight_config.enable
768# endif
769 ) {
770 rgblight_layers_write();
771 }
772# endif
773
670# ifdef RGBLIGHT_LED_MAP 774# ifdef RGBLIGHT_LED_MAP
671 LED_TYPE led0[RGBLED_NUM]; 775 LED_TYPE led0[RGBLED_NUM];
672 for (uint8_t i = 0; i < RGBLED_NUM; i++) { 776 for (uint8_t i = 0; i < RGBLED_NUM; i++) {
673 led0[i] = led[pgm_read_byte(&led_map[i])]; 777 led0[i] = led[pgm_read_byte(&led_map[i])];
674 } 778 }
675 start_led = led0 + clipping_start_pos; 779 start_led = led0 + rgblight_ranges.clipping_start_pos;
676# else 780# else
677 start_led = led + clipping_start_pos; 781 start_led = led + rgblight_ranges.clipping_start_pos;
678# endif 782# endif
679 783
680#ifdef RGBW 784# ifdef RGBW
681 for (uint8_t i = 0; i < num_leds; i++) { 785 for (uint8_t i = 0; i < num_leds; i++) {
682 convert_rgb_to_rgbw(&start_led[i]); 786 convert_rgb_to_rgbw(&start_led[i]);
683 } 787 }
684#endif 788# endif
685 // MxSS custom 789 // MxSS custom
686 switch (fled_mode) { 790 switch (fled_mode) {
687 case FLED_OFF: 791 case FLED_OFF:
688 setrgb(0, 0, 0, &led[RGBLIGHT_FLED1]);
689 setrgb(0, 0, 0, &led[RGBLIGHT_FLED2]);
690 break;
691
692 case FLED_INDI:
693 copyrgb(&fleds[0], &led[RGBLIGHT_FLED1]);
694 copyrgb(&fleds[1], &led[RGBLIGHT_FLED2]);
695 break;
696
697 case FLED_RGB:
698 if (fled_hs[0].hue == 0 && fled_hs[0].hue == 0 &&
699 (rgblight_status.base_mode == RGBLIGHT_MODE_SNAKE ||
700 rgblight_status.base_mode == RGBLIGHT_MODE_KNIGHT))
701 setrgb(0, 0, 0, &led[RGBLIGHT_FLED1]); 792 setrgb(0, 0, 0, &led[RGBLIGHT_FLED1]);
702 else 793 setrgb(0, 0, 0, &led[RGBLIGHT_FLED2]);
703 sethsv(fled_hs[0].hue, fled_hs[0].sat, fled_val, &led[RGBLIGHT_FLED1]); 794 break;
795
796 case FLED_INDI:
797 copyrgb(&fleds[0], &led[RGBLIGHT_FLED1]);
798 copyrgb(&fleds[1], &led[RGBLIGHT_FLED2]);
799 break;
704 800
705 if (fled_hs[1].hue == 0 && fled_hs[1].hue == 0 && 801 case FLED_RGB:
802 if (fled_hs[0].hue == 0 && fled_hs[0].hue == 0 &&
706 (rgblight_status.base_mode == RGBLIGHT_MODE_SNAKE || 803 (rgblight_status.base_mode == RGBLIGHT_MODE_SNAKE ||
707 rgblight_status.base_mode == RGBLIGHT_MODE_KNIGHT)) 804 rgblight_status.base_mode == RGBLIGHT_MODE_KNIGHT))
708 setrgb(0, 0, 0, &led[RGBLIGHT_FLED2]); 805 setrgb(0, 0, 0, &led[RGBLIGHT_FLED1]);
709 else 806 else
710 sethsv(fled_hs[1].hue, fled_hs[1].sat, fled_val, &led[RGBLIGHT_FLED2]); 807 sethsv(fled_hs[0].hue, fled_hs[0].sat, fled_val, &led[RGBLIGHT_FLED1]);
711 break;
712 808
713 default: 809 if (fled_hs[1].hue == 0 && fled_hs[1].hue == 0 &&
714 break; 810 (rgblight_status.base_mode == RGBLIGHT_MODE_SNAKE ||
715 } 811 rgblight_status.base_mode == RGBLIGHT_MODE_KNIGHT))
812 setrgb(0, 0, 0, &led[RGBLIGHT_FLED2]);
813 else
814 sethsv(fled_hs[1].hue, fled_hs[1].sat, fled_val, &led[RGBLIGHT_FLED2]);
815 break;
816 default:
817 break;
818 }
716 819
717 ws2812_setleds(start_led, num_leds); 820 rgblight_call_driver(start_led, num_leds);
718} 821}
719#endif 822#endif
720 823
@@ -731,6 +834,11 @@ void rgblight_get_syncinfo(rgblight_syncinfo_t *syncinfo) {
731 834
732/* for split keyboard slave side */ 835/* for split keyboard slave side */
733void rgblight_update_sync(rgblight_syncinfo_t *syncinfo, bool write_to_eeprom) { 836void rgblight_update_sync(rgblight_syncinfo_t *syncinfo, bool write_to_eeprom) {
837# ifdef RGBLIGHT_LAYERS
838 if (syncinfo->status.change_flags & RGBLIGHT_STATUS_CHANGE_LAYERS) {
839 rgblight_status.enabled_layer_mask = syncinfo->status.enabled_layer_mask;
840 }
841# endif
734 if (syncinfo->status.change_flags & RGBLIGHT_STATUS_CHANGE_MODE) { 842 if (syncinfo->status.change_flags & RGBLIGHT_STATUS_CHANGE_MODE) {
735 if (syncinfo->config.enable) { 843 if (syncinfo->config.enable) {
736 rgblight_config.enable = 1; // == rgblight_enable_noeeprom(); 844 rgblight_config.enable = 1; // == rgblight_enable_noeeprom();
@@ -893,6 +1001,12 @@ void rgblight_task(void) {
893 effect_func = (effect_func_t)rgblight_effect_alternating; 1001 effect_func = (effect_func_t)rgblight_effect_alternating;
894 } 1002 }
895# endif 1003# endif
1004# ifdef RGBLIGHT_EFFECT_TWINKLE
1005 else if (rgblight_status.base_mode == RGBLIGHT_MODE_TWINKLE) {
1006 interval_time = get_interval_time(&RGBLED_TWINKLE_INTERVALS[delta % 3], 5, 50);
1007 effect_func = (effect_func_t)rgblight_effect_twinkle;
1008 }
1009# endif
896 if (animation_status.restart) { 1010 if (animation_status.restart) {
897 animation_status.restart = false; 1011 animation_status.restart = false;
898 animation_status.last_timer = timer_read() - interval_time - 1; 1012 animation_status.last_timer = timer_read() - interval_time - 1;
@@ -922,6 +1036,10 @@ void rgblight_task(void) {
922# endif 1036# endif
923 } 1037 }
924 } 1038 }
1039
1040# ifdef RGBLIGHT_LAYER_BLINK
1041 rgblight_unblink_layers();
1042# endif
925} 1043}
926 1044
927#endif /* RGBLIGHT_USE_TIMER */ 1045#endif /* RGBLIGHT_USE_TIMER */
@@ -972,9 +1090,9 @@ void rgblight_effect_rainbow_swirl(animation_status_t *anim) {
972 uint8_t hue; 1090 uint8_t hue;
973 uint8_t i; 1091 uint8_t i;
974 1092
975 for (i = 0; i < effect_num_leds; i++) { 1093 for (i = 0; i < rgblight_ranges.effect_num_leds; i++) {
976 hue = (RGBLIGHT_RAINBOW_SWIRL_RANGE / effect_num_leds * i + anim->current_hue); 1094 hue = (RGBLIGHT_RAINBOW_SWIRL_RANGE / rgblight_ranges.effect_num_leds * i + anim->current_hue);
977 sethsv(hue, rgblight_config.sat, rgblight_config.val, (LED_TYPE *)&led[i + effect_start_pos]); 1095 sethsv(hue, rgblight_config.sat, rgblight_config.val, (LED_TYPE *)&led[i + rgblight_ranges.effect_start_pos]);
978 } 1096 }
979 rgblight_set(); 1097 rgblight_set();
980 1098
@@ -1002,7 +1120,7 @@ void rgblight_effect_snake(animation_status_t *anim) {
1002# if defined(RGBLIGHT_SPLIT) && !defined(RGBLIGHT_SPLIT_NO_ANIMATION_SYNC) 1120# if defined(RGBLIGHT_SPLIT) && !defined(RGBLIGHT_SPLIT_NO_ANIMATION_SYNC)
1003 if (anim->pos == 0) { // restart signal 1121 if (anim->pos == 0) { // restart signal
1004 if (increment == 1) { 1122 if (increment == 1) {
1005 pos = effect_num_leds - 1; 1123 pos = rgblight_ranges.effect_num_leds - 1;
1006 } else { 1124 } else {
1007 pos = 0; 1125 pos = 0;
1008 } 1126 }
@@ -1014,8 +1132,8 @@ void rgblight_effect_snake(animation_status_t *anim) {
1014 fled_hs[0].hue = fled_hs[1].hue = 0; 1132 fled_hs[0].hue = fled_hs[1].hue = 0;
1015 fled_hs[0].sat = fled_hs[1].sat = 0; 1133 fled_hs[0].sat = fled_hs[1].sat = 0;
1016 1134
1017 for (i = 0; i < effect_num_leds; i++) { 1135 for (i = 0; i < rgblight_ranges.effect_num_leds; i++) {
1018 LED_TYPE *ledp = led + i + effect_start_pos; 1136 LED_TYPE *ledp = led + i + rgblight_ranges.effect_start_pos;
1019 ledp->r = 0; 1137 ledp->r = 0;
1020 ledp->g = 0; 1138 ledp->g = 0;
1021 ledp->b = 0; 1139 ledp->b = 0;
@@ -1028,7 +1146,7 @@ void rgblight_effect_snake(animation_status_t *anim) {
1028 k = k % RGBLED_NUM; 1146 k = k % RGBLED_NUM;
1029 } 1147 }
1030 if (k < 0) { 1148 if (k < 0) {
1031 k = k + effect_num_leds; 1149 k = k + rgblight_ranges.effect_num_leds;
1032 } 1150 }
1033 if (i == k) { 1151 if (i == k) {
1034 sethsv(rgblight_config.hue, rgblight_config.sat, (uint8_t)(rgblight_config.val * (RGBLIGHT_EFFECT_SNAKE_LENGTH - j) / RGBLIGHT_EFFECT_SNAKE_LENGTH), ledp); 1152 sethsv(rgblight_config.hue, rgblight_config.sat, (uint8_t)(rgblight_config.val * (RGBLIGHT_EFFECT_SNAKE_LENGTH - j) / RGBLIGHT_EFFECT_SNAKE_LENGTH), ledp);
@@ -1038,7 +1156,7 @@ void rgblight_effect_snake(animation_status_t *anim) {
1038 rgblight_set(); 1156 rgblight_set();
1039 if (increment == 1) { 1157 if (increment == 1) {
1040 if (pos - 1 < 0) { 1158 if (pos - 1 < 0) {
1041 pos = effect_num_leds - 1; 1159 pos = rgblight_ranges.effect_num_leds - 1;
1042# if defined(RGBLIGHT_SPLIT) && !defined(RGBLIGHT_SPLIT_NO_ANIMATION_SYNC) 1160# if defined(RGBLIGHT_SPLIT) && !defined(RGBLIGHT_SPLIT_NO_ANIMATION_SYNC)
1043 anim->pos = 0; 1161 anim->pos = 0;
1044# endif 1162# endif
@@ -1049,7 +1167,7 @@ void rgblight_effect_snake(animation_status_t *anim) {
1049# endif 1167# endif
1050 } 1168 }
1051 } else { 1169 } else {
1052 pos = (pos + 1) % effect_num_leds; 1170 pos = (pos + 1) % rgblight_ranges.effect_num_leds;
1053# if defined(RGBLIGHT_SPLIT) && !defined(RGBLIGHT_SPLIT_NO_ANIMATION_SYNC) 1171# if defined(RGBLIGHT_SPLIT) && !defined(RGBLIGHT_SPLIT_NO_ANIMATION_SYNC)
1054 anim->pos = pos; 1172 anim->pos = pos;
1055# endif 1173# endif
@@ -1075,7 +1193,7 @@ void rgblight_effect_knight(animation_status_t *anim) {
1075 } 1193 }
1076# endif 1194# endif
1077 // Set all the LEDs to 0 1195 // Set all the LEDs to 0
1078 for (i = effect_start_pos; i < effect_end_pos; i++) { 1196 for (i = rgblight_ranges.effect_start_pos; i < rgblight_ranges.effect_end_pos; i++) {
1079 led[i].r = 0; 1197 led[i].r = 0;
1080 led[i].g = 0; 1198 led[i].g = 0;
1081 led[i].b = 0; 1199 led[i].b = 0;
@@ -1085,7 +1203,7 @@ void rgblight_effect_knight(animation_status_t *anim) {
1085 } 1203 }
1086 // Determine which LEDs should be lit up 1204 // Determine which LEDs should be lit up
1087 for (i = 0; i < RGBLIGHT_EFFECT_KNIGHT_LED_NUM; i++) { 1205 for (i = 0; i < RGBLIGHT_EFFECT_KNIGHT_LED_NUM; i++) {
1088 cur = (i + RGBLIGHT_EFFECT_KNIGHT_OFFSET) % effect_num_leds + effect_start_pos; 1206 cur = (i + RGBLIGHT_EFFECT_KNIGHT_OFFSET) % rgblight_ranges.effect_num_leds + rgblight_ranges.effect_start_pos;
1089 1207
1090 if (i >= low_bound && i <= high_bound) { 1208 if (i >= low_bound && i <= high_bound) {
1091 sethsv(rgblight_config.hue, rgblight_config.sat, rgblight_config.val, (LED_TYPE *)&led[cur]); 1209 sethsv(rgblight_config.hue, rgblight_config.sat, rgblight_config.val, (LED_TYPE *)&led[cur]);
@@ -1124,16 +1242,39 @@ void rgblight_effect_knight(animation_status_t *anim) {
1124#endif 1242#endif
1125 1243
1126#ifdef RGBLIGHT_EFFECT_CHRISTMAS 1244#ifdef RGBLIGHT_EFFECT_CHRISTMAS
1127void rgblight_effect_christmas(animation_status_t *anim) { 1245# define CUBED(x) ((x) * (x) * (x))
1128 uint8_t hue;
1129 uint8_t i;
1130 1246
1131 anim->current_offset = (anim->current_offset + 1) % 2; 1247/**
1132 for (i = 0; i < effect_num_leds; i++) { 1248 * Christmas lights effect, with a smooth animation between red & green.
1133 hue = 0 + ((i / RGBLIGHT_EFFECT_CHRISTMAS_STEP + anim->current_offset) % 2) * 85; 1249 */
1134 sethsv(hue, rgblight_config.sat, rgblight_config.val, (LED_TYPE *)&led[i + effect_start_pos]); 1250void rgblight_effect_christmas(animation_status_t *anim) {
1251 static int8_t increment = 1;
1252 const uint8_t max_pos = 32;
1253 const uint8_t hue_green = 85;
1254
1255 uint32_t xa;
1256 uint8_t hue, val;
1257 uint8_t i;
1258
1259 // The effect works by animating anim->pos from 0 to 32 and back to 0.
1260 // The pos is used in a cubic bezier formula to ease-in-out between red and green, leaving the interpolated colors visible as short as possible.
1261 xa = CUBED((uint32_t)anim->pos);
1262 hue = ((uint32_t)hue_green) * xa / (xa + CUBED((uint32_t)(max_pos - anim->pos)));
1263 // Additionally, these interpolated colors get shown with a slightly darker value, to make them less prominent than the main colors.
1264 val = 255 - (3 * (hue < hue_green / 2 ? hue : hue_green - hue) / 2);
1265
1266 for (i = 0; i < rgblight_ranges.effect_num_leds; i++) {
1267 uint8_t local_hue = (i / RGBLIGHT_EFFECT_CHRISTMAS_STEP) % 2 ? hue : hue_green - hue;
1268 sethsv(local_hue, rgblight_config.sat, val, (LED_TYPE *)&led[i + rgblight_ranges.effect_start_pos]);
1135 } 1269 }
1136 rgblight_set(); 1270 rgblight_set();
1271
1272 if (anim->pos == 0) {
1273 increment = 1;
1274 } else if (anim->pos == max_pos) {
1275 increment = -1;
1276 }
1277 anim->pos += increment;
1137} 1278}
1138#endif 1279#endif
1139 1280
@@ -1183,11 +1324,11 @@ void rgblight_effect_rgbtest(animation_status_t *anim) {
1183 1324
1184#ifdef RGBLIGHT_EFFECT_ALTERNATING 1325#ifdef RGBLIGHT_EFFECT_ALTERNATING
1185void rgblight_effect_alternating(animation_status_t *anim) { 1326void rgblight_effect_alternating(animation_status_t *anim) {
1186 for (int i = 0; i < effect_num_leds; i++) { 1327 for (int i = 0; i < rgblight_ranges.effect_num_leds; i++) {
1187 LED_TYPE *ledp = led + i + effect_start_pos; 1328 LED_TYPE *ledp = led + i + rgblight_ranges.effect_start_pos;
1188 if (i < effect_num_leds / 2 && anim->pos) { 1329 if (i < rgblight_ranges.effect_num_leds / 2 && anim->pos) {
1189 sethsv(rgblight_config.hue, rgblight_config.sat, rgblight_config.val, ledp); 1330 sethsv(rgblight_config.hue, rgblight_config.sat, rgblight_config.val, ledp);
1190 } else if (i >= effect_num_leds / 2 && !anim->pos) { 1331 } else if (i >= rgblight_ranges.effect_num_leds / 2 && !anim->pos) {
1191 sethsv(rgblight_config.hue, rgblight_config.sat, rgblight_config.val, ledp); 1332 sethsv(rgblight_config.hue, rgblight_config.sat, rgblight_config.val, ledp);
1192 } else { 1333 } else {
1193 sethsv(rgblight_config.hue, rgblight_config.sat, 0, ledp); 1334 sethsv(rgblight_config.hue, rgblight_config.sat, 0, ledp);
@@ -1197,3 +1338,58 @@ void rgblight_effect_alternating(animation_status_t *anim) {
1197 anim->pos = (anim->pos + 1) % 2; 1338 anim->pos = (anim->pos + 1) % 2;
1198} 1339}
1199#endif 1340#endif
1341
1342#ifdef RGBLIGHT_EFFECT_TWINKLE
1343__attribute__((weak)) const uint8_t RGBLED_TWINKLE_INTERVALS[] PROGMEM = {50, 25, 10};
1344
1345typedef struct PACKED {
1346 HSV hsv;
1347 uint8_t life;
1348 bool up;
1349} TwinkleState;
1350
1351static TwinkleState led_twinkle_state[RGBLED_NUM];
1352
1353void rgblight_effect_twinkle(animation_status_t *anim) {
1354 bool random_color = anim->delta / 3;
1355 bool restart = anim->pos == 0;
1356 anim->pos = 1;
1357
1358 for (uint8_t i = 0; i < rgblight_ranges.effect_num_leds; i++) {
1359 TwinkleState *t = &(led_twinkle_state[i]);
1360 HSV * c = &(t->hsv);
1361 if (restart) {
1362 // Restart
1363 t->life = 0;
1364 t->hsv.v = 0;
1365 } else if (t->life) {
1366 // This LED is already on, either brightening or dimming
1367 t->life--;
1368 uint8_t on = t->up ? RGBLIGHT_EFFECT_TWINKLE_LIFE - t->life : t->life;
1369 c->v = (uint16_t)rgblight_config.val * on / RGBLIGHT_EFFECT_TWINKLE_LIFE;
1370 if (t->life == 0 && t->up) {
1371 t->up = false;
1372 t->life = RGBLIGHT_EFFECT_TWINKLE_LIFE;
1373 }
1374 if (!random_color) {
1375 c->h = rgblight_config.hue;
1376 c->s = rgblight_config.sat;
1377 }
1378 } else if (rand() < RAND_MAX * RGBLIGHT_EFFECT_TWINKLE_PROBABILITY) {
1379 // This LED is off, but was randomly selected to start brightening
1380 c->h = random_color ? rand() % 0xFF : rgblight_config.hue;
1381 c->s = random_color ? (rand() % (rgblight_config.sat / 2)) + (rgblight_config.sat / 2) : rgblight_config.sat;
1382 c->v = 0;
1383 t->life = RGBLIGHT_EFFECT_TWINKLE_LIFE;
1384 t->up = true;
1385 } else {
1386 // This LED is off, and was NOT selected to start brightening
1387 }
1388
1389 LED_TYPE *ledp = led + i + rgblight_ranges.effect_start_pos;
1390 sethsv(c->h, c->s, c->v, ledp);
1391 }
1392
1393 rgblight_set();
1394}
1395#endif