diff options
Diffstat (limited to 'quantum/rgblight')
| -rw-r--r-- | quantum/rgblight/rgblight.c | 1390 | ||||
| -rw-r--r-- | quantum/rgblight/rgblight.h | 434 | ||||
| -rw-r--r-- | quantum/rgblight/rgblight_breathe_table.h | 117 | ||||
| -rw-r--r-- | quantum/rgblight/rgblight_list.h | 136 | ||||
| -rw-r--r-- | quantum/rgblight/rgblight_modes.h | 75 | ||||
| -rw-r--r-- | quantum/rgblight/rgblight_post_config.h | 5 | 
6 files changed, 2157 insertions, 0 deletions
| diff --git a/quantum/rgblight/rgblight.c b/quantum/rgblight/rgblight.c new file mode 100644 index 0000000000..148dae78f4 --- /dev/null +++ b/quantum/rgblight/rgblight.c @@ -0,0 +1,1390 @@ +/* Copyright 2016-2017 Yang Liu + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program.  If not, see <http://www.gnu.org/licenses/>. + */ +#include <math.h> +#include <string.h> +#include <stdlib.h> +#include "wait.h" +#include "progmem.h" +#include "sync_timer.h" +#include "rgblight.h" +#include "color.h" +#include "debug.h" +#include "led_tables.h" +#include <lib/lib8tion/lib8tion.h> +#ifdef EEPROM_ENABLE +#    include "eeprom.h" +#endif +#ifdef VELOCIKEY_ENABLE +#    include "velocikey.h" +#endif + +#ifndef MIN +#    define MIN(a, b) (((a) < (b)) ? (a) : (b)) +#endif +#ifndef MAX +#    define MAX(a, b) (((a) > (b)) ? (a) : (b)) +#endif + +#ifdef RGBLIGHT_SPLIT +/* for split keyboard */ +#    define RGBLIGHT_SPLIT_SET_CHANGE_MODE rgblight_status.change_flags |= RGBLIGHT_STATUS_CHANGE_MODE +#    define RGBLIGHT_SPLIT_SET_CHANGE_HSVS rgblight_status.change_flags |= RGBLIGHT_STATUS_CHANGE_HSVS +#    define RGBLIGHT_SPLIT_SET_CHANGE_MODEHSVS rgblight_status.change_flags |= (RGBLIGHT_STATUS_CHANGE_MODE | RGBLIGHT_STATUS_CHANGE_HSVS) +#    define RGBLIGHT_SPLIT_SET_CHANGE_LAYERS rgblight_status.change_flags |= RGBLIGHT_STATUS_CHANGE_LAYERS +#    define RGBLIGHT_SPLIT_SET_CHANGE_TIMER_ENABLE rgblight_status.change_flags |= RGBLIGHT_STATUS_CHANGE_TIMER +#    define RGBLIGHT_SPLIT_ANIMATION_TICK rgblight_status.change_flags |= RGBLIGHT_STATUS_ANIMATION_TICK +#else +#    define RGBLIGHT_SPLIT_SET_CHANGE_MODE +#    define RGBLIGHT_SPLIT_SET_CHANGE_HSVS +#    define RGBLIGHT_SPLIT_SET_CHANGE_MODEHSVS +#    define RGBLIGHT_SPLIT_SET_CHANGE_LAYERS +#    define RGBLIGHT_SPLIT_SET_CHANGE_TIMER_ENABLE +#    define RGBLIGHT_SPLIT_ANIMATION_TICK +#endif + +#define _RGBM_SINGLE_STATIC(sym) RGBLIGHT_MODE_##sym, +#define _RGBM_SINGLE_DYNAMIC(sym) +#define _RGBM_MULTI_STATIC(sym) RGBLIGHT_MODE_##sym, +#define _RGBM_MULTI_DYNAMIC(sym) +#define _RGBM_TMP_STATIC(sym, msym) RGBLIGHT_MODE_##sym, +#define _RGBM_TMP_DYNAMIC(sym, msym) +static uint8_t static_effect_table[] = { +#include "rgblight_modes.h" +}; + +#define _RGBM_SINGLE_STATIC(sym) RGBLIGHT_MODE_##sym, +#define _RGBM_SINGLE_DYNAMIC(sym) RGBLIGHT_MODE_##sym, +#define _RGBM_MULTI_STATIC(sym) RGBLIGHT_MODE_##sym, +#define _RGBM_MULTI_DYNAMIC(sym) RGBLIGHT_MODE_##sym, +#define _RGBM_TMP_STATIC(sym, msym) RGBLIGHT_MODE_##msym, +#define _RGBM_TMP_DYNAMIC(sym, msym) RGBLIGHT_MODE_##msym, +static uint8_t mode_base_table[] = { +    0,  // RGBLIGHT_MODE_zero +#include "rgblight_modes.h" +}; + +#if !defined(RGBLIGHT_DEFAULT_MODE) +#    define RGBLIGHT_DEFAULT_MODE RGBLIGHT_MODE_STATIC_LIGHT +#endif + +#if !defined(RGBLIGHT_DEFAULT_HUE) +#    define RGBLIGHT_DEFAULT_HUE 0 +#endif + +#if !defined(RGBLIGHT_DEFAULT_SAT) +#    define RGBLIGHT_DEFAULT_SAT UINT8_MAX +#endif + +#if !defined(RGBLIGHT_DEFAULT_VAL) +#    define RGBLIGHT_DEFAULT_VAL RGBLIGHT_LIMIT_VAL +#endif + +#if !defined(RGBLIGHT_DEFAULT_SPD) +#    define RGBLIGHT_DEFAULT_SPD 0 +#endif + +static inline int is_static_effect(uint8_t mode) { return memchr(static_effect_table, mode, sizeof(static_effect_table)) != NULL; } + +#ifdef RGBLIGHT_LED_MAP +const uint8_t led_map[] PROGMEM = RGBLIGHT_LED_MAP; +#endif + +#ifdef RGBLIGHT_EFFECT_STATIC_GRADIENT +__attribute__((weak)) const uint8_t RGBLED_GRADIENT_RANGES[] PROGMEM = {255, 170, 127, 85, 64}; +#endif + +rgblight_config_t rgblight_config; +rgblight_status_t rgblight_status         = {.timer_enabled = false}; +bool              is_rgblight_initialized = false; + +#ifdef RGBLIGHT_SLEEP +static bool is_suspended; +static bool pre_suspend_enabled; +#endif + +#ifdef RGBLIGHT_USE_TIMER +animation_status_t animation_status = {}; +#endif + +#ifndef LED_ARRAY +LED_TYPE led[RGBLED_NUM]; +#    define LED_ARRAY led +#endif + +#ifdef RGBLIGHT_LAYERS +rgblight_segment_t const *const *rgblight_layers = NULL; +#endif + +rgblight_ranges_t rgblight_ranges = {0, RGBLED_NUM, 0, RGBLED_NUM, RGBLED_NUM}; + +void rgblight_set_clipping_range(uint8_t start_pos, uint8_t num_leds) { +    rgblight_ranges.clipping_start_pos = start_pos; +    rgblight_ranges.clipping_num_leds  = num_leds; +} + +void rgblight_set_effect_range(uint8_t start_pos, uint8_t num_leds) { +    if (start_pos >= RGBLED_NUM) return; +    if (start_pos + num_leds > RGBLED_NUM) return; +    rgblight_ranges.effect_start_pos = start_pos; +    rgblight_ranges.effect_end_pos   = start_pos + num_leds; +    rgblight_ranges.effect_num_leds  = num_leds; +} + +__attribute__((weak)) RGB rgblight_hsv_to_rgb(HSV hsv) { return hsv_to_rgb(hsv); } + +void sethsv_raw(uint8_t hue, uint8_t sat, uint8_t val, LED_TYPE *led1) { +    HSV hsv = {hue, sat, val}; +    RGB rgb = rgblight_hsv_to_rgb(hsv); +    setrgb(rgb.r, rgb.g, rgb.b, led1); +} + +void sethsv(uint8_t hue, uint8_t sat, uint8_t val, LED_TYPE *led1) { sethsv_raw(hue, sat, val > RGBLIGHT_LIMIT_VAL ? RGBLIGHT_LIMIT_VAL : val, led1); } + +void setrgb(uint8_t r, uint8_t g, uint8_t b, LED_TYPE *led1) { +    led1->r = r; +    led1->g = g; +    led1->b = b; +#ifdef RGBW +    led1->w = 0; +#endif +} + +void rgblight_check_config(void) { +    /* Add some out of bound checks for RGB light config */ + +    if (rgblight_config.mode < RGBLIGHT_MODE_STATIC_LIGHT) { +        rgblight_config.mode = RGBLIGHT_MODE_STATIC_LIGHT; +    } else if (rgblight_config.mode > RGBLIGHT_MODES) { +        rgblight_config.mode = RGBLIGHT_MODES; +    } + +    if (rgblight_config.val > RGBLIGHT_LIMIT_VAL) { +        rgblight_config.val = RGBLIGHT_LIMIT_VAL; +    } +} + +uint32_t eeconfig_read_rgblight(void) { +#ifdef EEPROM_ENABLE +    return eeprom_read_dword(EECONFIG_RGBLIGHT); +#else +    return 0; +#endif +} + +void eeconfig_update_rgblight(uint32_t val) { +#ifdef EEPROM_ENABLE +    rgblight_check_config(); +    eeprom_update_dword(EECONFIG_RGBLIGHT, val); +#endif +} + +void eeconfig_update_rgblight_current(void) { eeconfig_update_rgblight(rgblight_config.raw); } + +void eeconfig_update_rgblight_default(void) { +    rgblight_config.enable = 1; +    rgblight_config.mode   = RGBLIGHT_DEFAULT_MODE; +    rgblight_config.hue    = RGBLIGHT_DEFAULT_HUE; +    rgblight_config.sat    = RGBLIGHT_DEFAULT_SAT; +    rgblight_config.val    = RGBLIGHT_DEFAULT_VAL; +    rgblight_config.speed  = RGBLIGHT_DEFAULT_SPD; +    RGBLIGHT_SPLIT_SET_CHANGE_MODEHSVS; +    eeconfig_update_rgblight(rgblight_config.raw); +} + +void eeconfig_debug_rgblight(void) { +    dprintf("rgblight_config EEPROM:\n"); +    dprintf("rgblight_config.enable = %d\n", rgblight_config.enable); +    dprintf("rghlight_config.mode = %d\n", rgblight_config.mode); +    dprintf("rgblight_config.hue = %d\n", rgblight_config.hue); +    dprintf("rgblight_config.sat = %d\n", rgblight_config.sat); +    dprintf("rgblight_config.val = %d\n", rgblight_config.val); +    dprintf("rgblight_config.speed = %d\n", rgblight_config.speed); +} + +void rgblight_init(void) { +    /* if already initialized, don't do it again. +       If you must do it again, extern this and set to false, first. +       This is a dirty, dirty hack until proper hooks can be added for keyboard startup. */ +    if (is_rgblight_initialized) { +        return; +    } + +    dprintf("rgblight_init called.\n"); +    dprintf("rgblight_init start!\n"); +    if (!eeconfig_is_enabled()) { +        dprintf("rgblight_init eeconfig is not enabled.\n"); +        eeconfig_init(); +        eeconfig_update_rgblight_default(); +    } +    rgblight_config.raw = eeconfig_read_rgblight(); +    RGBLIGHT_SPLIT_SET_CHANGE_MODEHSVS; +    if (!rgblight_config.mode) { +        dprintf("rgblight_init rgblight_config.mode = 0. Write default values to EEPROM.\n"); +        eeconfig_update_rgblight_default(); +        rgblight_config.raw = eeconfig_read_rgblight(); +    } +    rgblight_check_config(); + +    eeconfig_debug_rgblight();  // display current eeprom values + +    rgblight_timer_init();  // setup the timer + +    if (rgblight_config.enable) { +        rgblight_mode_noeeprom(rgblight_config.mode); +    } + +    is_rgblight_initialized = true; +} + +void rgblight_reload_from_eeprom(void) { +    /* Reset back to what we have in eeprom */ +    rgblight_config.raw = eeconfig_read_rgblight(); +    RGBLIGHT_SPLIT_SET_CHANGE_MODEHSVS; +    rgblight_check_config(); +    eeconfig_debug_rgblight();  // display current eeprom values +    if (rgblight_config.enable) { +        rgblight_mode_noeeprom(rgblight_config.mode); +    } +} + +uint32_t rgblight_read_dword(void) { return rgblight_config.raw; } + +void rgblight_update_dword(uint32_t dword) { +    RGBLIGHT_SPLIT_SET_CHANGE_MODEHSVS; +    rgblight_config.raw = dword; +    if (rgblight_config.enable) +        rgblight_mode_noeeprom(rgblight_config.mode); +    else { +        rgblight_timer_disable(); +        rgblight_set(); +    } +} + +void rgblight_increase(void) { +    uint8_t mode = 0; +    if (rgblight_config.mode < RGBLIGHT_MODES) { +        mode = rgblight_config.mode + 1; +    } +    rgblight_mode(mode); +} +void rgblight_decrease(void) { +    uint8_t mode = 0; +    // Mode will never be < 1. If it ever is, eeprom needs to be initialized. +    if (rgblight_config.mode > RGBLIGHT_MODE_STATIC_LIGHT) { +        mode = rgblight_config.mode - 1; +    } +    rgblight_mode(mode); +} +void rgblight_step_helper(bool write_to_eeprom) { +    uint8_t mode = 0; +    mode         = rgblight_config.mode + 1; +    if (mode > RGBLIGHT_MODES) { +        mode = 1; +    } +    rgblight_mode_eeprom_helper(mode, write_to_eeprom); +} +void rgblight_step_noeeprom(void) { rgblight_step_helper(false); } +void rgblight_step(void) { rgblight_step_helper(true); } +void rgblight_step_reverse_helper(bool write_to_eeprom) { +    uint8_t mode = 0; +    mode         = rgblight_config.mode - 1; +    if (mode < 1) { +        mode = RGBLIGHT_MODES; +    } +    rgblight_mode_eeprom_helper(mode, write_to_eeprom); +} +void rgblight_step_reverse_noeeprom(void) { rgblight_step_reverse_helper(false); } +void rgblight_step_reverse(void) { rgblight_step_reverse_helper(true); } + +uint8_t rgblight_get_mode(void) { +    if (!rgblight_config.enable) { +        return false; +    } + +    return rgblight_config.mode; +} + +void rgblight_mode_eeprom_helper(uint8_t mode, bool write_to_eeprom) { +    if (!rgblight_config.enable) { +        return; +    } +    if (mode < RGBLIGHT_MODE_STATIC_LIGHT) { +        rgblight_config.mode = RGBLIGHT_MODE_STATIC_LIGHT; +    } else if (mode > RGBLIGHT_MODES) { +        rgblight_config.mode = RGBLIGHT_MODES; +    } else { +        rgblight_config.mode = mode; +    } +    RGBLIGHT_SPLIT_SET_CHANGE_MODE; +    if (write_to_eeprom) { +        eeconfig_update_rgblight(rgblight_config.raw); +        dprintf("rgblight mode [EEPROM]: %u\n", rgblight_config.mode); +    } else { +        dprintf("rgblight mode [NOEEPROM]: %u\n", rgblight_config.mode); +    } +    if (is_static_effect(rgblight_config.mode)) { +        rgblight_timer_disable(); +    } else { +        rgblight_timer_enable(); +    } +#ifdef RGBLIGHT_USE_TIMER +    animation_status.restart = true; +#endif +    rgblight_sethsv_noeeprom(rgblight_config.hue, rgblight_config.sat, rgblight_config.val); +} + +void rgblight_mode(uint8_t mode) { rgblight_mode_eeprom_helper(mode, true); } + +void rgblight_mode_noeeprom(uint8_t mode) { rgblight_mode_eeprom_helper(mode, false); } + +void rgblight_toggle(void) { +    dprintf("rgblight toggle [EEPROM]: rgblight_config.enable = %u\n", !rgblight_config.enable); +    if (rgblight_config.enable) { +        rgblight_disable(); +    } else { +        rgblight_enable(); +    } +} + +void rgblight_toggle_noeeprom(void) { +    dprintf("rgblight toggle [NOEEPROM]: rgblight_config.enable = %u\n", !rgblight_config.enable); +    if (rgblight_config.enable) { +        rgblight_disable_noeeprom(); +    } else { +        rgblight_enable_noeeprom(); +    } +} + +void rgblight_enable(void) { +    rgblight_config.enable = 1; +    // No need to update EEPROM here. rgblight_mode() will do that, actually +    // eeconfig_update_rgblight(rgblight_config.raw); +    dprintf("rgblight enable [EEPROM]: rgblight_config.enable = %u\n", rgblight_config.enable); +    rgblight_mode(rgblight_config.mode); +} + +void rgblight_enable_noeeprom(void) { +    rgblight_config.enable = 1; +    dprintf("rgblight enable [NOEEPROM]: rgblight_config.enable = %u\n", rgblight_config.enable); +    rgblight_mode_noeeprom(rgblight_config.mode); +} + +void rgblight_disable(void) { +    rgblight_config.enable = 0; +    eeconfig_update_rgblight(rgblight_config.raw); +    dprintf("rgblight disable [EEPROM]: rgblight_config.enable = %u\n", rgblight_config.enable); +    rgblight_timer_disable(); +    RGBLIGHT_SPLIT_SET_CHANGE_MODE; +    wait_ms(50); +    rgblight_set(); +} + +void rgblight_disable_noeeprom(void) { +    rgblight_config.enable = 0; +    dprintf("rgblight disable [NOEEPROM]: rgblight_config.enable = %u\n", rgblight_config.enable); +    rgblight_timer_disable(); +    RGBLIGHT_SPLIT_SET_CHANGE_MODE; +    wait_ms(50); +    rgblight_set(); +} + +bool rgblight_is_enabled(void) { return rgblight_config.enable; } + +void rgblight_increase_hue_helper(bool write_to_eeprom) { +    uint8_t hue = rgblight_config.hue + RGBLIGHT_HUE_STEP; +    rgblight_sethsv_eeprom_helper(hue, rgblight_config.sat, rgblight_config.val, write_to_eeprom); +} +void rgblight_increase_hue_noeeprom(void) { rgblight_increase_hue_helper(false); } +void rgblight_increase_hue(void) { rgblight_increase_hue_helper(true); } +void rgblight_decrease_hue_helper(bool write_to_eeprom) { +    uint8_t hue = rgblight_config.hue - RGBLIGHT_HUE_STEP; +    rgblight_sethsv_eeprom_helper(hue, rgblight_config.sat, rgblight_config.val, write_to_eeprom); +} +void rgblight_decrease_hue_noeeprom(void) { rgblight_decrease_hue_helper(false); } +void rgblight_decrease_hue(void) { rgblight_decrease_hue_helper(true); } +void rgblight_increase_sat_helper(bool write_to_eeprom) { +    uint8_t sat = qadd8(rgblight_config.sat, RGBLIGHT_SAT_STEP); +    rgblight_sethsv_eeprom_helper(rgblight_config.hue, sat, rgblight_config.val, write_to_eeprom); +} +void rgblight_increase_sat_noeeprom(void) { rgblight_increase_sat_helper(false); } +void rgblight_increase_sat(void) { rgblight_increase_sat_helper(true); } +void rgblight_decrease_sat_helper(bool write_to_eeprom) { +    uint8_t sat = qsub8(rgblight_config.sat, RGBLIGHT_SAT_STEP); +    rgblight_sethsv_eeprom_helper(rgblight_config.hue, sat, rgblight_config.val, write_to_eeprom); +} +void rgblight_decrease_sat_noeeprom(void) { rgblight_decrease_sat_helper(false); } +void rgblight_decrease_sat(void) { rgblight_decrease_sat_helper(true); } +void rgblight_increase_val_helper(bool write_to_eeprom) { +    uint8_t val = qadd8(rgblight_config.val, RGBLIGHT_VAL_STEP); +    rgblight_sethsv_eeprom_helper(rgblight_config.hue, rgblight_config.sat, val, write_to_eeprom); +} +void rgblight_increase_val_noeeprom(void) { rgblight_increase_val_helper(false); } +void rgblight_increase_val(void) { rgblight_increase_val_helper(true); } +void rgblight_decrease_val_helper(bool write_to_eeprom) { +    uint8_t val = qsub8(rgblight_config.val, RGBLIGHT_VAL_STEP); +    rgblight_sethsv_eeprom_helper(rgblight_config.hue, rgblight_config.sat, val, write_to_eeprom); +} +void rgblight_decrease_val_noeeprom(void) { rgblight_decrease_val_helper(false); } +void rgblight_decrease_val(void) { rgblight_decrease_val_helper(true); } + +void rgblight_increase_speed_helper(bool write_to_eeprom) { +    if (rgblight_config.speed < 3) rgblight_config.speed++; +    // RGBLIGHT_SPLIT_SET_CHANGE_HSVS; // NEED? +    if (write_to_eeprom) { +        eeconfig_update_rgblight(rgblight_config.raw);  // EECONFIG needs to be increased to support this +    } +} +void rgblight_increase_speed(void) { rgblight_increase_speed_helper(true); } +void rgblight_increase_speed_noeeprom(void) { rgblight_increase_speed_helper(false); } + +void rgblight_decrease_speed_helper(bool write_to_eeprom) { +    if (rgblight_config.speed > 0) rgblight_config.speed--; +    // RGBLIGHT_SPLIT_SET_CHANGE_HSVS; // NEED?? +    if (write_to_eeprom) { +        eeconfig_update_rgblight(rgblight_config.raw);  // EECONFIG needs to be increased to support this +    } +} +void rgblight_decrease_speed(void) { rgblight_decrease_speed_helper(true); } +void rgblight_decrease_speed_noeeprom(void) { rgblight_decrease_speed_helper(false); } + +void rgblight_sethsv_noeeprom_old(uint8_t hue, uint8_t sat, uint8_t val) { +    if (rgblight_config.enable) { +        LED_TYPE tmp_led; +        sethsv(hue, sat, val, &tmp_led); +        rgblight_setrgb(tmp_led.r, tmp_led.g, tmp_led.b); +    } +} + +void rgblight_sethsv_eeprom_helper(uint8_t hue, uint8_t sat, uint8_t val, bool write_to_eeprom) { +    if (rgblight_config.enable) { +        rgblight_status.base_mode = mode_base_table[rgblight_config.mode]; +        if (rgblight_config.mode == RGBLIGHT_MODE_STATIC_LIGHT) { +            // same static color +            LED_TYPE tmp_led; +            sethsv(hue, sat, val, &tmp_led); +            rgblight_setrgb(tmp_led.r, tmp_led.g, tmp_led.b); +        } else { +            // all LEDs in same color +            if (1 == 0) {  // dummy +            } +#ifdef RGBLIGHT_EFFECT_BREATHING +            else if (rgblight_status.base_mode == RGBLIGHT_MODE_BREATHING) { +                // breathing mode, ignore the change of val, use in memory value instead +                val = rgblight_config.val; +            } +#endif +#ifdef RGBLIGHT_EFFECT_RAINBOW_MOOD +            else if (rgblight_status.base_mode == RGBLIGHT_MODE_RAINBOW_MOOD) { +                // rainbow mood, ignore the change of hue +                hue = rgblight_config.hue; +            } +#endif +#ifdef RGBLIGHT_EFFECT_RAINBOW_SWIRL +            else if (rgblight_status.base_mode == RGBLIGHT_MODE_RAINBOW_SWIRL) { +                // rainbow swirl, ignore the change of hue +                hue = rgblight_config.hue; +            } +#endif +#ifdef RGBLIGHT_EFFECT_STATIC_GRADIENT +            else if (rgblight_status.base_mode == RGBLIGHT_MODE_STATIC_GRADIENT) { +                // static gradient +                uint8_t delta     = rgblight_config.mode - rgblight_status.base_mode; +                bool    direction = (delta % 2) == 0; +#    ifdef __AVR__ +                // probably due to how pgm_read_word is defined for ARM, but the ARM compiler really hates this line +                uint8_t range = pgm_read_word(&RGBLED_GRADIENT_RANGES[delta / 2]); +#    else +                uint8_t range = RGBLED_GRADIENT_RANGES[delta / 2]; +#    endif +                for (uint8_t i = 0; i < rgblight_ranges.effect_num_leds; i++) { +                    uint8_t _hue = ((uint16_t)i * (uint16_t)range) / rgblight_ranges.effect_num_leds; +                    if (direction) { +                        _hue = hue + _hue; +                    } else { +                        _hue = hue - _hue; +                    } +                    dprintf("rgblight rainbow set hsv: %d,%d,%d,%u\n", i, _hue, direction, range); +                    sethsv(_hue, sat, val, (LED_TYPE *)&led[i + rgblight_ranges.effect_start_pos]); +                } +                rgblight_set(); +            } +#endif +        } +#ifdef RGBLIGHT_SPLIT +        if (rgblight_config.hue != hue || rgblight_config.sat != sat || rgblight_config.val != val) { +            RGBLIGHT_SPLIT_SET_CHANGE_HSVS; +        } +#endif +        rgblight_config.hue = hue; +        rgblight_config.sat = sat; +        rgblight_config.val = val; +        if (write_to_eeprom) { +            eeconfig_update_rgblight(rgblight_config.raw); +            dprintf("rgblight set hsv [EEPROM]: %u,%u,%u\n", rgblight_config.hue, rgblight_config.sat, rgblight_config.val); +        } else { +            dprintf("rgblight set hsv [NOEEPROM]: %u,%u,%u\n", rgblight_config.hue, rgblight_config.sat, rgblight_config.val); +        } +    } +} + +void rgblight_sethsv(uint8_t hue, uint8_t sat, uint8_t val) { rgblight_sethsv_eeprom_helper(hue, sat, val, true); } + +void rgblight_sethsv_noeeprom(uint8_t hue, uint8_t sat, uint8_t val) { rgblight_sethsv_eeprom_helper(hue, sat, val, false); } + +uint8_t rgblight_get_speed(void) { return rgblight_config.speed; } + +void rgblight_set_speed_eeprom_helper(uint8_t speed, bool write_to_eeprom) { +    rgblight_config.speed = speed; +    if (write_to_eeprom) { +        eeconfig_update_rgblight(rgblight_config.raw);  // EECONFIG needs to be increased to support this +        dprintf("rgblight set speed [EEPROM]: %u\n", rgblight_config.speed); +    } else { +        dprintf("rgblight set speed [NOEEPROM]: %u\n", rgblight_config.speed); +    } +} + +void rgblight_set_speed(uint8_t speed) { rgblight_set_speed_eeprom_helper(speed, true); } + +void rgblight_set_speed_noeeprom(uint8_t speed) { rgblight_set_speed_eeprom_helper(speed, false); } + +uint8_t rgblight_get_hue(void) { return rgblight_config.hue; } + +uint8_t rgblight_get_sat(void) { return rgblight_config.sat; } + +uint8_t rgblight_get_val(void) { return rgblight_config.val; } + +HSV rgblight_get_hsv(void) { return (HSV){rgblight_config.hue, rgblight_config.sat, rgblight_config.val}; } + +void rgblight_setrgb(uint8_t r, uint8_t g, uint8_t b) { +    if (!rgblight_config.enable) { +        return; +    } + +    for (uint8_t i = rgblight_ranges.effect_start_pos; i < rgblight_ranges.effect_end_pos; i++) { +        led[i].r = r; +        led[i].g = g; +        led[i].b = b; +#ifdef RGBW +        led[i].w = 0; +#endif +    } +    rgblight_set(); +} + +void rgblight_setrgb_at(uint8_t r, uint8_t g, uint8_t b, uint8_t index) { +    if (!rgblight_config.enable || index >= RGBLED_NUM) { +        return; +    } + +    led[index].r = r; +    led[index].g = g; +    led[index].b = b; +#ifdef RGBW +    led[index].w = 0; +#endif +    rgblight_set(); +} + +void rgblight_sethsv_at(uint8_t hue, uint8_t sat, uint8_t val, uint8_t index) { +    if (!rgblight_config.enable) { +        return; +    } + +    LED_TYPE tmp_led; +    sethsv(hue, sat, val, &tmp_led); +    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) || defined(RGBLIGHT_EFFECT_TWINKLE) + +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; +    } + +    for (uint8_t i = start; i < end; i++) { +        led[i].r = r; +        led[i].g = g; +        led[i].b = b; +#ifdef RGBW +        led[i].w = 0; +#endif +    } +    rgblight_set(); +    wait_ms(1); +} + +void rgblight_sethsv_range(uint8_t hue, uint8_t sat, uint8_t val, uint8_t start, uint8_t end) { +    if (!rgblight_config.enable) { +        return; +    } + +    LED_TYPE tmp_led; +    sethsv(hue, sat, val, &tmp_led); +    rgblight_setrgb_range(tmp_led.r, tmp_led.g, tmp_led.b, start, end); +} + +#ifndef RGBLIGHT_SPLIT +void rgblight_setrgb_master(uint8_t r, uint8_t g, uint8_t b) { rgblight_setrgb_range(r, g, b, 0, (uint8_t)RGBLED_NUM / 2); } + +void rgblight_setrgb_slave(uint8_t r, uint8_t g, uint8_t b) { rgblight_setrgb_range(r, g, b, (uint8_t)RGBLED_NUM / 2, (uint8_t)RGBLED_NUM); } + +void rgblight_sethsv_master(uint8_t hue, uint8_t sat, uint8_t val) { rgblight_sethsv_range(hue, sat, val, 0, (uint8_t)RGBLED_NUM / 2); } + +void 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); } +#endif  // ifndef RGBLIGHT_SPLIT + +#ifdef RGBLIGHT_LAYERS +void rgblight_set_layer_state(uint8_t layer, bool enabled) { +    rgblight_layer_mask_t mask = (rgblight_layer_mask_t)1 << layer; +    if (enabled) { +        rgblight_status.enabled_layer_mask |= mask; +    } else { +        rgblight_status.enabled_layer_mask &= ~mask; +    } +    RGBLIGHT_SPLIT_SET_CHANGE_LAYERS; +    // Static modes don't have a ticker running to update the LEDs +    if (rgblight_status.timer_enabled == false) { +        rgblight_mode_noeeprom(rgblight_config.mode); +    } + +#    ifdef RGBLIGHT_LAYERS_OVERRIDE_RGB_OFF +    // If not enabled, then nothing else will actually set the LEDs... +    if (!rgblight_config.enable) { +        rgblight_set(); +    } +#    endif +} + +bool rgblight_get_layer_state(uint8_t layer) { +    rgblight_layer_mask_t mask = (rgblight_layer_mask_t)1 << layer; +    return (rgblight_status.enabled_layer_mask & mask) != 0; +} + +// Write any enabled LED layers into the buffer +static void rgblight_layers_write(void) { +#    ifdef RGBLIGHT_LAYERS_RETAIN_VAL +    uint8_t current_val = rgblight_get_val(); +#    endif +    uint8_t i = 0; +    // For each layer +    for (const rgblight_segment_t *const *layer_ptr = rgblight_layers; i < RGBLIGHT_MAX_LAYERS; layer_ptr++, i++) { +        if (!rgblight_get_layer_state(i)) { +            continue;  // Layer is disabled +        } +        const rgblight_segment_t *segment_ptr = pgm_read_ptr(layer_ptr); +        if (segment_ptr == NULL) { +            break;  // No more layers +        } +        // For each segment +        while (1) { +            rgblight_segment_t segment; +            memcpy_P(&segment, segment_ptr, sizeof(rgblight_segment_t)); +            if (segment.index == RGBLIGHT_END_SEGMENT_INDEX) { +                break;  // No more segments +            } +            // Write segment.count LEDs +            LED_TYPE *const limit = &led[MIN(segment.index + segment.count, RGBLED_NUM)]; +            for (LED_TYPE *led_ptr = &led[segment.index]; led_ptr < limit; led_ptr++) { +#    ifdef RGBLIGHT_LAYERS_RETAIN_VAL +                sethsv(segment.hue, segment.sat, current_val, led_ptr); +#    else +                sethsv(segment.hue, segment.sat, segment.val, led_ptr); +#    endif +            } +            segment_ptr++; +        } +    } +} + +#    ifdef RGBLIGHT_LAYER_BLINK +rgblight_layer_mask_t _blinking_layer_mask = 0; +static uint16_t       _repeat_timer; +static uint8_t        _times_remaining; +static uint16_t       _dur; + +void rgblight_blink_layer(uint8_t layer, uint16_t duration_ms) { rgblight_blink_layer_repeat(layer, duration_ms, 1); } + +void rgblight_blink_layer_repeat(uint8_t layer, uint16_t duration_ms, uint8_t times) { +    _times_remaining = times * 2; +    _dur             = duration_ms; + +    rgblight_set_layer_state(layer, true); +    _times_remaining--; +    _blinking_layer_mask |= (rgblight_layer_mask_t)1 << layer; +    _repeat_timer = sync_timer_read() + duration_ms; +} + +void rgblight_blink_layer_repeat_helper(void) { +    if (_blinking_layer_mask != 0 && timer_expired(sync_timer_read(), _repeat_timer)) { +        for (uint8_t layer = 0; layer < RGBLIGHT_MAX_LAYERS; layer++) { +            if ((_blinking_layer_mask & (rgblight_layer_mask_t)1 << layer) != 0 && _times_remaining > 0) { +                if (_times_remaining % 2 == 1) { +                    rgblight_set_layer_state(layer, false); +                } else { +                    rgblight_set_layer_state(layer, true); +                } +                _times_remaining--; +                _repeat_timer = sync_timer_read() + _dur; +            } +        } +        if (_times_remaining <= 0) { +            _blinking_layer_mask = 0; +        } +    } +} +#    endif + +#endif + +#ifdef RGBLIGHT_SLEEP + +void rgblight_suspend(void) { +    rgblight_timer_disable(); +    if (!is_suspended) { +        is_suspended        = true; +        pre_suspend_enabled = rgblight_config.enable; + +#    ifdef RGBLIGHT_LAYER_BLINK +        // make sure any layer blinks don't come back after suspend +        rgblight_status.enabled_layer_mask &= ~_blinking_layer_mask; +        _blinking_layer_mask = 0; +#    endif + +        rgblight_disable_noeeprom(); +    } +} + +void rgblight_wakeup(void) { +    is_suspended = false; + +    if (pre_suspend_enabled) { +        rgblight_enable_noeeprom(); +    } +#    ifdef RGBLIGHT_LAYERS_OVERRIDE_RGB_OFF +    // Need this or else the LEDs won't be set +    else if (rgblight_status.enabled_layer_mask != 0) { +        rgblight_set(); +    } +#    endif + +    rgblight_timer_enable(); +} + +#endif + +__attribute__((weak)) void rgblight_call_driver(LED_TYPE *start_led, uint8_t num_leds) { ws2812_setleds(start_led, num_leds); } + +#ifndef RGBLIGHT_CUSTOM_DRIVER + +void rgblight_set(void) { +    LED_TYPE *start_led; +    uint8_t   num_leds = rgblight_ranges.clipping_num_leds; + +    if (!rgblight_config.enable) { +        for (uint8_t i = rgblight_ranges.effect_start_pos; i < rgblight_ranges.effect_end_pos; i++) { +            led[i].r = 0; +            led[i].g = 0; +            led[i].b = 0; +#    ifdef RGBW +            led[i].w = 0; +#    endif +        } +    } + +#    ifdef RGBLIGHT_LAYERS +    if (rgblight_layers != NULL +#        if !defined(RGBLIGHT_LAYERS_OVERRIDE_RGB_OFF) +        && rgblight_config.enable +#        elif defined(RGBLIGHT_SLEEP) +        && !is_suspended +#        endif +    ) { +        rgblight_layers_write(); +    } +#    endif + +#    ifdef RGBLIGHT_LED_MAP +    LED_TYPE led0[RGBLED_NUM]; +    for (uint8_t i = 0; i < RGBLED_NUM; i++) { +        led0[i] = led[pgm_read_byte(&led_map[i])]; +    } +    start_led = led0 + rgblight_ranges.clipping_start_pos; +#    else +    start_led = led + rgblight_ranges.clipping_start_pos; +#    endif + +#    ifdef RGBW +    for (uint8_t i = 0; i < num_leds; i++) { +        convert_rgb_to_rgbw(&start_led[i]); +    } +#    endif +    rgblight_call_driver(start_led, num_leds); +} +#endif + +#ifdef RGBLIGHT_SPLIT +/* for split keyboard master side */ +uint8_t rgblight_get_change_flags(void) { return rgblight_status.change_flags; } + +void rgblight_clear_change_flags(void) { rgblight_status.change_flags = 0; } + +void rgblight_get_syncinfo(rgblight_syncinfo_t *syncinfo) { +    syncinfo->config = rgblight_config; +    syncinfo->status = rgblight_status; +} + +/* for split keyboard slave side */ +void rgblight_update_sync(rgblight_syncinfo_t *syncinfo, bool write_to_eeprom) { +#    ifdef RGBLIGHT_LAYERS +    if (syncinfo->status.change_flags & RGBLIGHT_STATUS_CHANGE_LAYERS) { +        rgblight_status.enabled_layer_mask = syncinfo->status.enabled_layer_mask; +    } +#    endif +    if (syncinfo->status.change_flags & RGBLIGHT_STATUS_CHANGE_MODE) { +        if (syncinfo->config.enable) { +            rgblight_config.enable = 1;  // == rgblight_enable_noeeprom(); +            rgblight_mode_eeprom_helper(syncinfo->config.mode, write_to_eeprom); +        } else { +            rgblight_disable_noeeprom(); +        } +    } +    if (syncinfo->status.change_flags & RGBLIGHT_STATUS_CHANGE_HSVS) { +        rgblight_sethsv_eeprom_helper(syncinfo->config.hue, syncinfo->config.sat, syncinfo->config.val, write_to_eeprom); +        // rgblight_config.speed = config->speed; // NEED??? +    } +#    ifdef RGBLIGHT_USE_TIMER +    if (syncinfo->status.change_flags & RGBLIGHT_STATUS_CHANGE_TIMER) { +        if (syncinfo->status.timer_enabled) { +            rgblight_timer_enable(); +        } else { +            rgblight_timer_disable(); +        } +    } +#        ifndef RGBLIGHT_SPLIT_NO_ANIMATION_SYNC +    if (syncinfo->status.change_flags & RGBLIGHT_STATUS_ANIMATION_TICK) { +        animation_status.restart = true; +    } +#        endif /* RGBLIGHT_SPLIT_NO_ANIMATION_SYNC */ +#    endif     /* RGBLIGHT_USE_TIMER */ +} +#endif /* RGBLIGHT_SPLIT */ + +#ifdef RGBLIGHT_USE_TIMER + +typedef void (*effect_func_t)(animation_status_t *anim); + +// Animation timer -- use system timer (AVR Timer0) +void rgblight_timer_init(void) { +    rgblight_status.timer_enabled = false; +    RGBLIGHT_SPLIT_SET_CHANGE_TIMER_ENABLE; +} +void rgblight_timer_enable(void) { +    if (!is_static_effect(rgblight_config.mode)) { +        rgblight_status.timer_enabled = true; +    } +    animation_status.last_timer = sync_timer_read(); +    RGBLIGHT_SPLIT_SET_CHANGE_TIMER_ENABLE; +    dprintf("rgblight timer enabled.\n"); +} +void rgblight_timer_disable(void) { +    rgblight_status.timer_enabled = false; +    RGBLIGHT_SPLIT_SET_CHANGE_TIMER_ENABLE; +    dprintf("rgblight timer disable.\n"); +} +void rgblight_timer_toggle(void) { +    dprintf("rgblight timer toggle.\n"); +    if (rgblight_status.timer_enabled) { +        rgblight_timer_disable(); +    } else { +        rgblight_timer_enable(); +    } +} + +void rgblight_show_solid_color(uint8_t r, uint8_t g, uint8_t b) { +    rgblight_enable(); +    rgblight_mode(RGBLIGHT_MODE_STATIC_LIGHT); +    rgblight_setrgb(r, g, b); +} + +static void rgblight_effect_dummy(animation_status_t *anim) { +    // do nothing +    /******** +    dprintf("rgblight_task() what happened?\n"); +    dprintf("is_static_effect %d\n", is_static_effect(rgblight_config.mode)); +    dprintf("mode = %d, base_mode = %d, timer_enabled %d, ", +            rgblight_config.mode, rgblight_status.base_mode, +            rgblight_status.timer_enabled); +    dprintf("last_timer = %d\n",anim->last_timer); +    **/ +} + +void rgblight_task(void) { +    if (rgblight_status.timer_enabled) { +        effect_func_t effect_func   = rgblight_effect_dummy; +        uint16_t      interval_time = 2000;  // dummy interval +        uint8_t       delta         = rgblight_config.mode - rgblight_status.base_mode; +        animation_status.delta      = delta; + +        // static light mode, do nothing here +        if (1 == 0) {  // dummy +        } +#    ifdef RGBLIGHT_EFFECT_BREATHING +        else if (rgblight_status.base_mode == RGBLIGHT_MODE_BREATHING) { +            // breathing mode +            interval_time = get_interval_time(&RGBLED_BREATHING_INTERVALS[delta], 1, 100); +            effect_func   = rgblight_effect_breathing; +        } +#    endif +#    ifdef RGBLIGHT_EFFECT_RAINBOW_MOOD +        else if (rgblight_status.base_mode == RGBLIGHT_MODE_RAINBOW_MOOD) { +            // rainbow mood mode +            interval_time = get_interval_time(&RGBLED_RAINBOW_MOOD_INTERVALS[delta], 5, 100); +            effect_func   = rgblight_effect_rainbow_mood; +        } +#    endif +#    ifdef RGBLIGHT_EFFECT_RAINBOW_SWIRL +        else if (rgblight_status.base_mode == RGBLIGHT_MODE_RAINBOW_SWIRL) { +            // rainbow swirl mode +            interval_time = get_interval_time(&RGBLED_RAINBOW_SWIRL_INTERVALS[delta / 2], 1, 100); +            effect_func   = rgblight_effect_rainbow_swirl; +        } +#    endif +#    ifdef RGBLIGHT_EFFECT_SNAKE +        else if (rgblight_status.base_mode == RGBLIGHT_MODE_SNAKE) { +            // snake mode +            interval_time = get_interval_time(&RGBLED_SNAKE_INTERVALS[delta / 2], 1, 200); +            effect_func   = rgblight_effect_snake; +        } +#    endif +#    ifdef RGBLIGHT_EFFECT_KNIGHT +        else if (rgblight_status.base_mode == RGBLIGHT_MODE_KNIGHT) { +            // knight mode +            interval_time = get_interval_time(&RGBLED_KNIGHT_INTERVALS[delta], 5, 100); +            effect_func   = rgblight_effect_knight; +        } +#    endif +#    ifdef RGBLIGHT_EFFECT_CHRISTMAS +        else if (rgblight_status.base_mode == RGBLIGHT_MODE_CHRISTMAS) { +            // christmas mode +            interval_time = RGBLIGHT_EFFECT_CHRISTMAS_INTERVAL; +            effect_func   = (effect_func_t)rgblight_effect_christmas; +        } +#    endif +#    ifdef RGBLIGHT_EFFECT_RGB_TEST +        else if (rgblight_status.base_mode == RGBLIGHT_MODE_RGB_TEST) { +            // RGB test mode +            interval_time = pgm_read_word(&RGBLED_RGBTEST_INTERVALS[0]); +            effect_func   = (effect_func_t)rgblight_effect_rgbtest; +        } +#    endif +#    ifdef RGBLIGHT_EFFECT_ALTERNATING +        else if (rgblight_status.base_mode == RGBLIGHT_MODE_ALTERNATING) { +            interval_time = 500; +            effect_func   = (effect_func_t)rgblight_effect_alternating; +        } +#    endif +#    ifdef RGBLIGHT_EFFECT_TWINKLE +        else if (rgblight_status.base_mode == RGBLIGHT_MODE_TWINKLE) { +            interval_time = get_interval_time(&RGBLED_TWINKLE_INTERVALS[delta % 3], 5, 30); +            effect_func   = (effect_func_t)rgblight_effect_twinkle; +        } +#    endif +        if (animation_status.restart) { +            animation_status.restart    = false; +            animation_status.last_timer = sync_timer_read(); +            animation_status.pos16      = 0;  // restart signal to local each effect +        } +        uint16_t now = sync_timer_read(); +        if (timer_expired(now, animation_status.last_timer)) { +#    if defined(RGBLIGHT_SPLIT) && !defined(RGBLIGHT_SPLIT_NO_ANIMATION_SYNC) +            static uint16_t report_last_timer = 0; +            static bool     tick_flag         = false; +            uint16_t        oldpos16; +            if (tick_flag) { +                tick_flag = false; +                if (timer_expired(now, report_last_timer)) { +                    report_last_timer += 30000; +                    dprintf("rgblight animation tick report to slave\n"); +                    RGBLIGHT_SPLIT_ANIMATION_TICK; +                } +            } +            oldpos16 = animation_status.pos16; +#    endif +            animation_status.last_timer += interval_time; +            effect_func(&animation_status); +#    if defined(RGBLIGHT_SPLIT) && !defined(RGBLIGHT_SPLIT_NO_ANIMATION_SYNC) +            if (animation_status.pos16 == 0 && oldpos16 != 0) { +                tick_flag = true; +            } +#    endif +        } +    } + +#    ifdef RGBLIGHT_LAYER_BLINK +    rgblight_blink_layer_repeat_helper(); +#    endif +} + +#endif /* RGBLIGHT_USE_TIMER */ + +#if defined(RGBLIGHT_EFFECT_BREATHING) || defined(RGBLIGHT_EFFECT_TWINKLE) + +#    ifndef RGBLIGHT_EFFECT_BREATHE_CENTER +#        ifndef RGBLIGHT_BREATHE_TABLE_SIZE +#            define RGBLIGHT_BREATHE_TABLE_SIZE 256  // 256 or 128 or 64 +#        endif +#        include <rgblight_breathe_table.h> +#    endif + +static uint8_t breathe_calc(uint8_t pos) { +    // http://sean.voisen.org/blog/2011/10/breathing-led-with-arduino/ +#    ifdef RGBLIGHT_EFFECT_BREATHE_TABLE +    return pgm_read_byte(&rgblight_effect_breathe_table[pos / table_scale]); +#    else +    return (exp(sin((pos / 255.0) * M_PI)) - RGBLIGHT_EFFECT_BREATHE_CENTER / M_E) * (RGBLIGHT_EFFECT_BREATHE_MAX / (M_E - 1 / M_E)); +#    endif +} + +#endif + +// Effects +#ifdef RGBLIGHT_EFFECT_BREATHING + +__attribute__((weak)) const uint8_t RGBLED_BREATHING_INTERVALS[] PROGMEM = {30, 20, 10, 5}; + +void rgblight_effect_breathing(animation_status_t *anim) { +    uint8_t val = breathe_calc(anim->pos); +    rgblight_sethsv_noeeprom_old(rgblight_config.hue, rgblight_config.sat, val); +    anim->pos = (anim->pos + 1); +} +#endif + +#ifdef RGBLIGHT_EFFECT_RAINBOW_MOOD +__attribute__((weak)) const uint8_t RGBLED_RAINBOW_MOOD_INTERVALS[] PROGMEM = {120, 60, 30}; + +void rgblight_effect_rainbow_mood(animation_status_t *anim) { +    rgblight_sethsv_noeeprom_old(anim->current_hue, rgblight_config.sat, rgblight_config.val); +    anim->current_hue++; +} +#endif + +#ifdef RGBLIGHT_EFFECT_RAINBOW_SWIRL +#    ifndef RGBLIGHT_RAINBOW_SWIRL_RANGE +#        define RGBLIGHT_RAINBOW_SWIRL_RANGE 255 +#    endif + +__attribute__((weak)) const uint8_t RGBLED_RAINBOW_SWIRL_INTERVALS[] PROGMEM = {100, 50, 20}; + +void rgblight_effect_rainbow_swirl(animation_status_t *anim) { +    uint8_t hue; +    uint8_t i; + +    for (i = 0; i < rgblight_ranges.effect_num_leds; i++) { +        hue = (RGBLIGHT_RAINBOW_SWIRL_RANGE / rgblight_ranges.effect_num_leds * i + anim->current_hue); +        sethsv(hue, rgblight_config.sat, rgblight_config.val, (LED_TYPE *)&led[i + rgblight_ranges.effect_start_pos]); +    } +    rgblight_set(); + +    if (anim->delta % 2) { +        anim->current_hue++; +    } else { +        anim->current_hue--; +    } +} +#endif + +#ifdef RGBLIGHT_EFFECT_SNAKE +__attribute__((weak)) const uint8_t RGBLED_SNAKE_INTERVALS[] PROGMEM = {100, 50, 20}; + +void rgblight_effect_snake(animation_status_t *anim) { +    static uint8_t pos = 0; +    uint8_t        i, j; +    int8_t         k; +    int8_t         increment = 1; + +    if (anim->delta % 2) { +        increment = -1; +    } + +#    if defined(RGBLIGHT_SPLIT) && !defined(RGBLIGHT_SPLIT_NO_ANIMATION_SYNC) +    if (anim->pos == 0) {  // restart signal +        if (increment == 1) { +            pos = rgblight_ranges.effect_num_leds - 1; +        } else { +            pos = 0; +        } +        anim->pos = 1; +    } +#    endif + +    for (i = 0; i < rgblight_ranges.effect_num_leds; i++) { +        LED_TYPE *ledp = led + i + rgblight_ranges.effect_start_pos; +        ledp->r        = 0; +        ledp->g        = 0; +        ledp->b        = 0; +#    ifdef RGBW +        ledp->w = 0; +#    endif +        for (j = 0; j < RGBLIGHT_EFFECT_SNAKE_LENGTH; j++) { +            k = pos + j * increment; +            if (k > RGBLED_NUM) { +                k = k % RGBLED_NUM; +            } +            if (k < 0) { +                k = k + rgblight_ranges.effect_num_leds; +            } +            if (i == k) { +                sethsv(rgblight_config.hue, rgblight_config.sat, (uint8_t)(rgblight_config.val * (RGBLIGHT_EFFECT_SNAKE_LENGTH - j) / RGBLIGHT_EFFECT_SNAKE_LENGTH), ledp); +            } +        } +    } +    rgblight_set(); +    if (increment == 1) { +        if (pos - 1 < 0) { +            pos = rgblight_ranges.effect_num_leds - 1; +#    if defined(RGBLIGHT_SPLIT) && !defined(RGBLIGHT_SPLIT_NO_ANIMATION_SYNC) +            anim->pos = 0; +#    endif +        } else { +            pos -= 1; +#    if defined(RGBLIGHT_SPLIT) && !defined(RGBLIGHT_SPLIT_NO_ANIMATION_SYNC) +            anim->pos = 1; +#    endif +        } +    } else { +        pos = (pos + 1) % rgblight_ranges.effect_num_leds; +#    if defined(RGBLIGHT_SPLIT) && !defined(RGBLIGHT_SPLIT_NO_ANIMATION_SYNC) +        anim->pos = pos; +#    endif +    } +} +#endif + +#ifdef RGBLIGHT_EFFECT_KNIGHT +__attribute__((weak)) const uint8_t RGBLED_KNIGHT_INTERVALS[] PROGMEM = {127, 63, 31}; + +void rgblight_effect_knight(animation_status_t *anim) { +    static int8_t low_bound  = 0; +    static int8_t high_bound = RGBLIGHT_EFFECT_KNIGHT_LENGTH - 1; +    static int8_t increment  = 1; +    uint8_t       i, cur; + +#    if defined(RGBLIGHT_SPLIT) && !defined(RGBLIGHT_SPLIT_NO_ANIMATION_SYNC) +    if (anim->pos == 0) {  // restart signal +        anim->pos  = 1; +        low_bound  = 0; +        high_bound = RGBLIGHT_EFFECT_KNIGHT_LENGTH - 1; +        increment  = 1; +    } +#    endif +    // Set all the LEDs to 0 +    for (i = rgblight_ranges.effect_start_pos; i < rgblight_ranges.effect_end_pos; i++) { +        led[i].r = 0; +        led[i].g = 0; +        led[i].b = 0; +#    ifdef RGBW +        led[i].w = 0; +#    endif +    } +    // Determine which LEDs should be lit up +    for (i = 0; i < RGBLIGHT_EFFECT_KNIGHT_LED_NUM; i++) { +        cur = (i + RGBLIGHT_EFFECT_KNIGHT_OFFSET) % rgblight_ranges.effect_num_leds + rgblight_ranges.effect_start_pos; + +        if (i >= low_bound && i <= high_bound) { +            sethsv(rgblight_config.hue, rgblight_config.sat, rgblight_config.val, (LED_TYPE *)&led[cur]); +        } else { +            led[cur].r = 0; +            led[cur].g = 0; +            led[cur].b = 0; +#    ifdef RGBW +            led[cur].w = 0; +#    endif +        } +    } +    rgblight_set(); + +    // Move from low_bound to high_bound changing the direction we increment each +    // time a boundary is hit. +    low_bound += increment; +    high_bound += increment; + +    if (high_bound <= 0 || low_bound >= RGBLIGHT_EFFECT_KNIGHT_LED_NUM - 1) { +        increment = -increment; +#    if defined(RGBLIGHT_SPLIT) && !defined(RGBLIGHT_SPLIT_NO_ANIMATION_SYNC) +        if (increment == 1) { +            anim->pos = 0; +        } +#    endif +    } +} +#endif + +#ifdef RGBLIGHT_EFFECT_CHRISTMAS +#    define CUBED(x) ((x) * (x) * (x)) + +/** + * Christmas lights effect, with a smooth animation between red & green. + */ +void rgblight_effect_christmas(animation_status_t *anim) { +    static int8_t increment = 1; +    const uint8_t max_pos   = 32; +    const uint8_t hue_green = 85; + +    uint32_t xa; +    uint8_t  hue, val; +    uint8_t  i; + +    // The effect works by animating anim->pos from 0 to 32 and back to 0. +    // 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. +    xa  = CUBED((uint32_t)anim->pos); +    hue = ((uint32_t)hue_green) * xa / (xa + CUBED((uint32_t)(max_pos - anim->pos))); +    // Additionally, these interpolated colors get shown with a slightly darker value, to make them less prominent than the main colors. +    val = 255 - (3 * (hue < hue_green / 2 ? hue : hue_green - hue) / 2); + +    for (i = 0; i < rgblight_ranges.effect_num_leds; i++) { +        uint8_t local_hue = (i / RGBLIGHT_EFFECT_CHRISTMAS_STEP) % 2 ? hue : hue_green - hue; +        sethsv(local_hue, rgblight_config.sat, val, (LED_TYPE *)&led[i + rgblight_ranges.effect_start_pos]); +    } +    rgblight_set(); + +    if (anim->pos == 0) { +        increment = 1; +    } else if (anim->pos == max_pos) { +        increment = -1; +    } +    anim->pos += increment; +} +#endif + +#ifdef RGBLIGHT_EFFECT_RGB_TEST +__attribute__((weak)) const uint16_t RGBLED_RGBTEST_INTERVALS[] PROGMEM = {1024}; + +void rgblight_effect_rgbtest(animation_status_t *anim) { +    static uint8_t maxval = 0; +    uint8_t        g; +    uint8_t        r; +    uint8_t        b; + +    if (maxval == 0) { +        LED_TYPE tmp_led; +        sethsv(0, 255, RGBLIGHT_LIMIT_VAL, &tmp_led); +        maxval = tmp_led.r; +    } +    g = r = b = 0; +    switch (anim->pos) { +        case 0: +            r = maxval; +            break; +        case 1: +            g = maxval; +            break; +        case 2: +            b = maxval; +            break; +    } +    rgblight_setrgb(r, g, b); +    anim->pos = (anim->pos + 1) % 3; +} +#endif + +#ifdef RGBLIGHT_EFFECT_ALTERNATING +void rgblight_effect_alternating(animation_status_t *anim) { +    for (int i = 0; i < rgblight_ranges.effect_num_leds; i++) { +        LED_TYPE *ledp = led + i + rgblight_ranges.effect_start_pos; +        if (i < rgblight_ranges.effect_num_leds / 2 && anim->pos) { +            sethsv(rgblight_config.hue, rgblight_config.sat, rgblight_config.val, ledp); +        } else if (i >= rgblight_ranges.effect_num_leds / 2 && !anim->pos) { +            sethsv(rgblight_config.hue, rgblight_config.sat, rgblight_config.val, ledp); +        } else { +            sethsv(rgblight_config.hue, rgblight_config.sat, 0, ledp); +        } +    } +    rgblight_set(); +    anim->pos = (anim->pos + 1) % 2; +} +#endif + +#ifdef RGBLIGHT_EFFECT_TWINKLE +__attribute__((weak)) const uint8_t RGBLED_TWINKLE_INTERVALS[] PROGMEM = {30, 15, 5}; + +typedef struct PACKED { +    HSV     hsv; +    uint8_t life; +    uint8_t max_life; +} TwinkleState; + +static TwinkleState led_twinkle_state[RGBLED_NUM]; + +void rgblight_effect_twinkle(animation_status_t *anim) { +    const bool random_color = anim->delta / 3; +    const bool restart      = anim->pos == 0; +    anim->pos               = 1; + +    const uint8_t bottom = breathe_calc(0); +    const uint8_t top    = breathe_calc(127); + +    uint8_t frac(uint8_t n, uint8_t d) { return (uint16_t)255 * n / d; } +    uint8_t scale(uint16_t v, uint8_t scale) { return (v * scale) >> 8; } + +    for (uint8_t i = 0; i < rgblight_ranges.effect_num_leds; i++) { +        TwinkleState *t = &(led_twinkle_state[i]); +        HSV *         c = &(t->hsv); + +        if (!random_color) { +            c->h = rgblight_config.hue; +            c->s = rgblight_config.sat; +        } + +        if (restart) { +            // Restart +            t->life = 0; +            c->v    = 0; +        } else if (t->life) { +            // This LED is already on, either brightening or dimming +            t->life--; +            uint8_t unscaled = frac(breathe_calc(frac(t->life, t->max_life)) - bottom, top - bottom); +            c->v             = scale(rgblight_config.val, unscaled); +        } else if (rand() < scale((uint16_t)RAND_MAX * RGBLIGHT_EFFECT_TWINKLE_PROBABILITY, 127 + rgblight_config.val / 2)) { +            // This LED is off, but was randomly selected to start brightening +            if (random_color) { +                c->h = rand() % 0xFF; +                c->s = (rand() % (rgblight_config.sat / 2)) + (rgblight_config.sat / 2); +            } +            c->v        = 0; +            t->max_life = MAX(20, MIN(RGBLIGHT_EFFECT_TWINKLE_LIFE, rgblight_config.val)); +            t->life     = t->max_life; +        } else { +            // This LED is off, and was NOT selected to start brightening +        } + +        LED_TYPE *ledp = led + i + rgblight_ranges.effect_start_pos; +        sethsv(c->h, c->s, c->v, ledp); +    } + +    rgblight_set(); +} +#endif diff --git a/quantum/rgblight/rgblight.h b/quantum/rgblight/rgblight.h new file mode 100644 index 0000000000..5b90b8f49e --- /dev/null +++ b/quantum/rgblight/rgblight.h @@ -0,0 +1,434 @@ +/* Copyright 2017 Yang Liu + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program.  If not, see <http://www.gnu.org/licenses/>. + */ + +#pragma once + +/***** rgblight_mode(mode)/rgblight_mode_noeeprom(mode) **** + + old mode number (before 0.6.117) to new mode name table + +|-----------------|-----------------------------------| +| old mode number | new mode name                     | +|-----------------|-----------------------------------| +|        1        | RGBLIGHT_MODE_STATIC_LIGHT        | +|        2        | RGBLIGHT_MODE_BREATHING           | +|        3        | RGBLIGHT_MODE_BREATHING + 1       | +|        4        | RGBLIGHT_MODE_BREATHING + 2       | +|        5        | RGBLIGHT_MODE_BREATHING + 3       | +|        6        | RGBLIGHT_MODE_RAINBOW_MOOD        | +|        7        | RGBLIGHT_MODE_RAINBOW_MOOD + 1    | +|        8        | RGBLIGHT_MODE_RAINBOW_MOOD + 2    | +|        9        | RGBLIGHT_MODE_RAINBOW_SWIRL       | +|       10        | RGBLIGHT_MODE_RAINBOW_SWIRL + 1   | +|       11        | RGBLIGHT_MODE_RAINBOW_SWIRL + 2   | +|       12        | RGBLIGHT_MODE_RAINBOW_SWIRL + 3   | +|       13        | RGBLIGHT_MODE_RAINBOW_SWIRL + 4   | +|       14        | RGBLIGHT_MODE_RAINBOW_SWIRL + 5   | +|       15        | RGBLIGHT_MODE_SNAKE               | +|       16        | RGBLIGHT_MODE_SNAKE + 1           | +|       17        | RGBLIGHT_MODE_SNAKE + 2           | +|       18        | RGBLIGHT_MODE_SNAKE + 3           | +|       19        | RGBLIGHT_MODE_SNAKE + 4           | +|       20        | RGBLIGHT_MODE_SNAKE + 5           | +|       21        | RGBLIGHT_MODE_KNIGHT              | +|       22        | RGBLIGHT_MODE_KNIGHT + 1          | +|       23        | RGBLIGHT_MODE_KNIGHT + 2          | +|       24        | RGBLIGHT_MODE_CHRISTMAS           | +|       25        | RGBLIGHT_MODE_STATIC_GRADIENT     | +|       26        | RGBLIGHT_MODE_STATIC_GRADIENT + 1 | +|       27        | RGBLIGHT_MODE_STATIC_GRADIENT + 2 | +|       28        | RGBLIGHT_MODE_STATIC_GRADIENT + 3 | +|       29        | RGBLIGHT_MODE_STATIC_GRADIENT + 4 | +|       30        | RGBLIGHT_MODE_STATIC_GRADIENT + 5 | +|       31        | RGBLIGHT_MODE_STATIC_GRADIENT + 6 | +|       32        | RGBLIGHT_MODE_STATIC_GRADIENT + 7 | +|       33        | RGBLIGHT_MODE_STATIC_GRADIENT + 8 | +|       34        | RGBLIGHT_MODE_STATIC_GRADIENT + 9 | +|       35        | RGBLIGHT_MODE_RGB_TEST            | +|       36        | RGBLIGHT_MODE_ALTERNATING         | +|       37        | RGBLIGHT_MODE_TWINKLE             | +|       38        | RGBLIGHT_MODE_TWINKLE + 1         | +|       39        | RGBLIGHT_MODE_TWINKLE + 2         | +|       40        | RGBLIGHT_MODE_TWINKLE + 3         | +|       41        | RGBLIGHT_MODE_TWINKLE + 4         | +|       42        | RGBLIGHT_MODE_TWINKLE + 5         | +|-----------------|-----------------------------------| + *****/ + +#ifdef RGBLIGHT_ANIMATIONS +// for backward compatibility +#    define RGBLIGHT_EFFECT_BREATHING +#    define RGBLIGHT_EFFECT_RAINBOW_MOOD +#    define RGBLIGHT_EFFECT_RAINBOW_SWIRL +#    define RGBLIGHT_EFFECT_SNAKE +#    define RGBLIGHT_EFFECT_KNIGHT +#    define RGBLIGHT_EFFECT_CHRISTMAS +#    define RGBLIGHT_EFFECT_STATIC_GRADIENT +#    define RGBLIGHT_EFFECT_RGB_TEST +#    define RGBLIGHT_EFFECT_ALTERNATING +#endif + +#ifdef RGBLIGHT_STATIC_PATTERNS +#    define RGBLIGHT_EFFECT_STATIC_GRADIENT +#endif + +// clang-format off + +// check dynamic animation effects chose ? +#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_CHRISTMAS)     \ +  || defined(RGBLIGHT_EFFECT_RGB_TEST)      \ +  || defined(RGBLIGHT_EFFECT_ALTERNATING)   \ +  || defined(RGBLIGHT_EFFECT_TWINKLE) +#    define RGBLIGHT_USE_TIMER +#endif + +// clang-format on + +#define _RGBM_SINGLE_STATIC(sym) RGBLIGHT_MODE_##sym, +#define _RGBM_SINGLE_DYNAMIC(sym) RGBLIGHT_MODE_##sym, +#define _RGBM_MULTI_STATIC(sym) RGBLIGHT_MODE_##sym, +#define _RGBM_MULTI_DYNAMIC(sym) RGBLIGHT_MODE_##sym, +#define _RGBM_TMP_STATIC(sym, msym) RGBLIGHT_MODE_##sym, +#define _RGBM_TMP_DYNAMIC(sym, msym) RGBLIGHT_MODE_##sym, +enum RGBLIGHT_EFFECT_MODE { +    RGBLIGHT_MODE_zero = 0, +#include "rgblight_modes.h" +    RGBLIGHT_MODE_last +}; + +#define RGBLIGHT_MODES (RGBLIGHT_MODE_last - 1) + +// sample: #define RGBLIGHT_EFFECT_BREATHE_CENTER   1.85 + +#ifndef RGBLIGHT_EFFECT_BREATHE_MAX +#    define RGBLIGHT_EFFECT_BREATHE_MAX 255  // 0-255 +#endif + +#ifndef RGBLIGHT_EFFECT_SNAKE_LENGTH +#    define RGBLIGHT_EFFECT_SNAKE_LENGTH 4 +#endif + +#ifndef RGBLIGHT_EFFECT_KNIGHT_LENGTH +#    define RGBLIGHT_EFFECT_KNIGHT_LENGTH 3 +#endif + +#ifndef RGBLIGHT_EFFECT_KNIGHT_OFFSET +#    define RGBLIGHT_EFFECT_KNIGHT_OFFSET 0 +#endif + +#ifndef RGBLIGHT_EFFECT_KNIGHT_LED_NUM +#    define RGBLIGHT_EFFECT_KNIGHT_LED_NUM (rgblight_ranges.effect_num_leds) +#endif + +#ifndef RGBLIGHT_EFFECT_CHRISTMAS_INTERVAL +#    define RGBLIGHT_EFFECT_CHRISTMAS_INTERVAL 40 +#endif + +#ifndef RGBLIGHT_EFFECT_CHRISTMAS_STEP +#    define RGBLIGHT_EFFECT_CHRISTMAS_STEP 2 +#endif + +#ifndef RGBLIGHT_EFFECT_TWINKLE_LIFE +#    define RGBLIGHT_EFFECT_TWINKLE_LIFE 200 +#endif + +#ifndef RGBLIGHT_EFFECT_TWINKLE_PROBABILITY +#    define RGBLIGHT_EFFECT_TWINKLE_PROBABILITY 1 / 127 +#endif + +#ifndef RGBLIGHT_HUE_STEP +#    define RGBLIGHT_HUE_STEP 8 +#endif +#ifndef RGBLIGHT_SAT_STEP +#    define RGBLIGHT_SAT_STEP 17 +#endif +#ifndef RGBLIGHT_VAL_STEP +#    define RGBLIGHT_VAL_STEP 17 +#endif +#ifndef RGBLIGHT_LIMIT_VAL +#    define RGBLIGHT_LIMIT_VAL 255 +#endif + +#include <stdint.h> +#include <stdbool.h> +#include "progmem.h" +#include "eeconfig.h" +#include "ws2812.h" +#include "color.h" +#include "rgblight_list.h" + +#ifdef RGBLIGHT_LAYERS +typedef struct { +    uint8_t index;  // The first LED to light +    uint8_t count;  // The number of LEDs to light +    uint8_t hue; +    uint8_t sat; +    uint8_t val; +} rgblight_segment_t; + +#    define RGBLIGHT_END_SEGMENT_INDEX (255) +#    define RGBLIGHT_END_SEGMENTS \ +        { RGBLIGHT_END_SEGMENT_INDEX, 0, 0, 0 } +#    ifndef RGBLIGHT_MAX_LAYERS +#        define RGBLIGHT_MAX_LAYERS 8 +#    endif +#    if RGBLIGHT_MAX_LAYERS <= 0 +#        error invalid RGBLIGHT_MAX_LAYERS value (must be >= 1) +#    elif RGBLIGHT_MAX_LAYERS <= 8 +typedef uint8_t rgblight_layer_mask_t; +#    elif RGBLIGHT_MAX_LAYERS <= 16 +typedef uint16_t rgblight_layer_mask_t; +#    elif RGBLIGHT_MAX_LAYERS <= 32 +typedef uint32_t rgblight_layer_mask_t; +#    else +#        error invalid RGBLIGHT_MAX_LAYERS value (must be <= 32) +#    endif +#    define RGBLIGHT_LAYER_SEGMENTS(...) \ +        { __VA_ARGS__, RGBLIGHT_END_SEGMENTS } +#    define RGBLIGHT_LAYERS_LIST(...) \ +        { __VA_ARGS__, NULL } + +// Get/set enabled rgblight layers +void rgblight_set_layer_state(uint8_t layer, bool enabled); +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); +void rgblight_blink_layer_repeat(uint8_t layer, uint16_t duration_ms, uint8_t times); +#    endif + +#endif + +extern LED_TYPE led[RGBLED_NUM]; + +extern const uint8_t  RGBLED_BREATHING_INTERVALS[4] PROGMEM; +extern const uint8_t  RGBLED_RAINBOW_MOOD_INTERVALS[3] PROGMEM; +extern const uint8_t  RGBLED_RAINBOW_SWIRL_INTERVALS[3] PROGMEM; +extern const uint8_t  RGBLED_SNAKE_INTERVALS[3] PROGMEM; +extern const uint8_t  RGBLED_KNIGHT_INTERVALS[3] PROGMEM; +extern const uint16_t RGBLED_RGBTEST_INTERVALS[1] PROGMEM; +extern const uint8_t  RGBLED_TWINKLE_INTERVALS[3] PROGMEM; +extern bool           is_rgblight_initialized; + +// Should stay in sycn with rgb matrix config as we reuse eeprom storage for both (for now) +typedef union { +    uint32_t raw; +    struct { +        bool    enable : 1; +        uint8_t mode : 7; +        uint8_t hue : 8; +        uint8_t sat : 8; +        uint8_t val : 8; +        uint8_t speed : 8;  // EECONFIG needs to be increased to support this +    }; +} rgblight_config_t; + +typedef struct _rgblight_status_t { +    uint8_t base_mode; +    bool    timer_enabled; +#ifdef RGBLIGHT_SPLIT +    uint8_t change_flags; +#endif +#ifdef RGBLIGHT_LAYERS +    rgblight_layer_mask_t enabled_layer_mask; +#endif +} rgblight_status_t; + +/* + * Structure for RGB Light clipping ranges + */ +typedef struct _rgblight_ranges_t { +    uint8_t clipping_start_pos; +    uint8_t clipping_num_leds; +    uint8_t effect_start_pos; +    uint8_t effect_end_pos; +    uint8_t effect_num_leds; +} rgblight_ranges_t; + +extern rgblight_ranges_t rgblight_ranges; + +/* === Utility Functions ===*/ +void sethsv(uint8_t hue, uint8_t sat, uint8_t val, LED_TYPE *led1); +void sethsv_raw(uint8_t hue, uint8_t sat, uint8_t val, LED_TYPE *led1);  // without RGBLIGHT_LIMIT_VAL check +void setrgb(uint8_t r, uint8_t g, uint8_t b, LED_TYPE *led1); + +/* === Low level Functions === */ +void rgblight_set(void); +void rgblight_set_clipping_range(uint8_t start_pos, uint8_t num_leds); + +/* === Effects and Animations Functions === */ +/*   effect range setting */ +void rgblight_set_effect_range(uint8_t start_pos, uint8_t num_leds); + +/*   direct operation */ +void rgblight_setrgb_at(uint8_t r, uint8_t g, uint8_t b, uint8_t index); +void rgblight_sethsv_at(uint8_t hue, uint8_t sat, uint8_t val, uint8_t index); +void rgblight_setrgb_range(uint8_t r, uint8_t g, uint8_t b, uint8_t start, uint8_t end); +void rgblight_sethsv_range(uint8_t hue, uint8_t sat, uint8_t val, uint8_t start, uint8_t end); +void rgblight_setrgb(uint8_t r, uint8_t g, uint8_t b); + +#ifndef RGBLIGHT_SPLIT +void rgblight_setrgb_master(uint8_t r, uint8_t g, uint8_t b); +void rgblight_setrgb_slave(uint8_t r, uint8_t g, uint8_t b); +void rgblight_sethsv_master(uint8_t hue, uint8_t sat, uint8_t val); +void rgblight_sethsv_slave(uint8_t hue, uint8_t sat, uint8_t val); +#endif + +/*   effect mode change */ +void rgblight_mode(uint8_t mode); +void rgblight_mode_noeeprom(uint8_t mode); +void rgblight_increase(void); +void rgblight_decrease(void); +void rgblight_step(void); +void rgblight_step_noeeprom(void); +void rgblight_step_reverse(void); +void rgblight_step_reverse_noeeprom(void); + +/*   effects mode disable/enable */ +void rgblight_toggle(void); +void rgblight_toggle_noeeprom(void); +void rgblight_enable(void); +void rgblight_enable_noeeprom(void); +void rgblight_disable(void); +void rgblight_disable_noeeprom(void); + +/*   hue, sat, val change */ +void rgblight_increase_hue(void); +void rgblight_increase_hue_noeeprom(void); +void rgblight_decrease_hue(void); +void rgblight_decrease_hue_noeeprom(void); +void rgblight_increase_sat(void); +void rgblight_increase_sat_noeeprom(void); +void rgblight_decrease_sat(void); +void rgblight_decrease_sat_noeeprom(void); +void rgblight_increase_val(void); +void rgblight_increase_val_noeeprom(void); +void rgblight_decrease_val(void); +void rgblight_decrease_val_noeeprom(void); +void rgblight_increase_speed(void); +void rgblight_increase_speed_noeeprom(void); +void rgblight_decrease_speed(void); +void rgblight_decrease_speed_noeeprom(void); +void rgblight_sethsv(uint8_t hue, uint8_t sat, uint8_t val); +void rgblight_sethsv_noeeprom(uint8_t hue, uint8_t sat, uint8_t val); + +/*   effect speed */ +uint8_t rgblight_get_speed(void); +void    rgblight_set_speed(uint8_t speed); +void    rgblight_set_speed_noeeprom(uint8_t speed); + +/*   reset */ +void rgblight_reload_from_eeprom(void); + +/*       query */ +uint8_t rgblight_get_mode(void); +uint8_t rgblight_get_hue(void); +uint8_t rgblight_get_sat(void); +uint8_t rgblight_get_val(void); +bool    rgblight_is_enabled(void); +HSV     rgblight_get_hsv(void); + +/* === qmk_firmware (core)internal Functions === */ +void     rgblight_init(void); +void     rgblight_suspend(void); +void     rgblight_wakeup(void); +uint32_t rgblight_read_dword(void); +void     rgblight_update_dword(uint32_t dword); +uint32_t eeconfig_read_rgblight(void); +void     eeconfig_update_rgblight(uint32_t val); +void     eeconfig_update_rgblight_current(void); +void     eeconfig_update_rgblight_default(void); +void     eeconfig_debug_rgblight(void); + +void rgb_matrix_increase(void); +void rgb_matrix_decrease(void); + +void rgblight_sethsv_eeprom_helper(uint8_t hue, uint8_t sat, uint8_t val, bool write_to_eeprom); +void rgblight_mode_eeprom_helper(uint8_t mode, bool write_to_eeprom); + +#define EZ_RGB(val) rgblight_show_solid_color((val >> 16) & 0xFF, (val >> 8) & 0xFF, val & 0xFF) +void rgblight_show_solid_color(uint8_t r, uint8_t g, uint8_t b); + +#ifdef RGBLIGHT_USE_TIMER +void rgblight_task(void); +void rgblight_timer_init(void); +void rgblight_timer_enable(void); +void rgblight_timer_disable(void); +void rgblight_timer_toggle(void); +#else +#    define rgblight_task() +#    define rgblight_timer_init() +#    define rgblight_timer_enable() +#    define rgblight_timer_disable() +#    define rgblight_timer_toggle() +#endif + +#ifdef RGBLIGHT_SPLIT +#    define RGBLIGHT_STATUS_CHANGE_MODE (1 << 0) +#    define RGBLIGHT_STATUS_CHANGE_HSVS (1 << 1) +#    define RGBLIGHT_STATUS_CHANGE_TIMER (1 << 2) +#    define RGBLIGHT_STATUS_ANIMATION_TICK (1 << 3) +#    define RGBLIGHT_STATUS_CHANGE_LAYERS (1 << 4) + +typedef struct _rgblight_syncinfo_t { +    rgblight_config_t config; +    rgblight_status_t status; +} rgblight_syncinfo_t; + +/* for split keyboard master side */ +uint8_t rgblight_get_change_flags(void); +void    rgblight_clear_change_flags(void); +void    rgblight_get_syncinfo(rgblight_syncinfo_t *syncinfo); +/* for split keyboard slave side */ +void rgblight_update_sync(rgblight_syncinfo_t *syncinfo, bool write_to_eeprom); +#endif + +#ifdef RGBLIGHT_USE_TIMER + +typedef struct _animation_status_t { +    uint16_t last_timer; +    uint8_t  delta; /* mode - base_mode */ +    bool     restart; +    union { +        uint16_t pos16; +        uint8_t  pos; +        int8_t   current_hue; +        uint16_t current_offset; +    }; +} animation_status_t; + +extern animation_status_t animation_status; + +void rgblight_effect_breathing(animation_status_t *anim); +void rgblight_effect_rainbow_mood(animation_status_t *anim); +void rgblight_effect_rainbow_swirl(animation_status_t *anim); +void rgblight_effect_snake(animation_status_t *anim); +void rgblight_effect_knight(animation_status_t *anim); +void rgblight_effect_christmas(animation_status_t *anim); +void rgblight_effect_rgbtest(animation_status_t *anim); +void rgblight_effect_alternating(animation_status_t *anim); +void rgblight_effect_twinkle(animation_status_t *anim); + +#endif diff --git a/quantum/rgblight/rgblight_breathe_table.h b/quantum/rgblight/rgblight_breathe_table.h new file mode 100644 index 0000000000..30245318b6 --- /dev/null +++ b/quantum/rgblight/rgblight_breathe_table.h @@ -0,0 +1,117 @@ +#pragma once + +#define RGBLIGHT_EFFECT_BREATHE_TABLE + +// clang-format off + +// Breathing center: 1.85 +// Breathing max:    255 + +const uint8_t PROGMEM rgblight_effect_breathe_table[] = { +#if RGBLIGHT_BREATHE_TABLE_SIZE == 256 +    0x22, 0x23, 0x25, 0x26, 0x28, 0x29, 0x2A, 0x2C, +    0x2D, 0x2F, 0x30, 0x32, 0x33, 0x35, 0x36, 0x38, +    0x3A, 0x3B, 0x3D, 0x3E, 0x40, 0x42, 0x43, 0x45, +    0x47, 0x49, 0x4A, 0x4C, 0x4E, 0x50, 0x51, 0x53, +    0x55, 0x57, 0x59, 0x5A, 0x5C, 0x5E, 0x60, 0x62, +    0x64, 0x66, 0x68, 0x69, 0x6B, 0x6D, 0x6F, 0x71, +    0x73, 0x75, 0x77, 0x79, 0x7B, 0x7D, 0x7F, 0x81, +    0x83, 0x85, 0x87, 0x89, 0x8A, 0x8C, 0x8E, 0x90, +    0x92, 0x94, 0x96, 0x98, 0x9A, 0x9C, 0x9E, 0x9F, +    0xA1, 0xA3, 0xA5, 0xA7, 0xA8, 0xAA, 0xAC, 0xAE, +    0xAF, 0xB1, 0xB3, 0xB4, 0xB6, 0xB8, 0xB9, 0xBB, +    0xBC, 0xBE, 0xBF, 0xC1, 0xC2, 0xC3, 0xC5, 0xC6, +    0xC7, 0xC9, 0xCA, 0xCB, 0xCC, 0xCD, 0xCE, 0xD0, +    0xD1, 0xD2, 0xD2, 0xD3, 0xD4, 0xD5, 0xD6, 0xD7, +    0xD7, 0xD8, 0xD9, 0xD9, 0xDA, 0xDA, 0xDB, 0xDB, +    0xDB, 0xDC, 0xDC, 0xDC, 0xDC, 0xDC, 0xDD, 0xDD, +    0xDD, 0xDD, 0xDC, 0xDC, 0xDC, 0xDC, 0xDC, 0xDB, +    0xDB, 0xDB, 0xDA, 0xDA, 0xD9, 0xD9, 0xD8, 0xD7, +    0xD7, 0xD6, 0xD5, 0xD4, 0xD3, 0xD2, 0xD2, 0xD1, +    0xD0, 0xCE, 0xCD, 0xCC, 0xCB, 0xCA, 0xC9, 0xC7, +    0xC6, 0xC5, 0xC3, 0xC2, 0xC1, 0xBF, 0xBE, 0xBC, +    0xBB, 0xB9, 0xB8, 0xB6, 0xB4, 0xB3, 0xB1, 0xAF, +    0xAE, 0xAC, 0xAA, 0xA8, 0xA7, 0xA5, 0xA3, 0xA1, +    0x9F, 0x9E, 0x9C, 0x9A, 0x98, 0x96, 0x94, 0x92, +    0x90, 0x8E, 0x8C, 0x8A, 0x89, 0x87, 0x85, 0x83, +    0x81, 0x7F, 0x7D, 0x7B, 0x79, 0x77, 0x75, 0x73, +    0x71, 0x6F, 0x6D, 0x6B, 0x69, 0x68, 0x66, 0x64, +    0x62, 0x60, 0x5E, 0x5C, 0x5A, 0x59, 0x57, 0x55, +    0x53, 0x51, 0x50, 0x4E, 0x4C, 0x4A, 0x49, 0x47, +    0x45, 0x43, 0x42, 0x40, 0x3E, 0x3D, 0x3B, 0x3A, +    0x38, 0x36, 0x35, 0x33, 0x32, 0x30, 0x2F, 0x2D, +    0x2C, 0x2A, 0x29, 0x28, 0x26, 0x25, 0x23, 0x22 +#endif + +#if RGBLIGHT_BREATHE_TABLE_SIZE == 128 +    0x22, 0x25, 0x28, 0x2A, +    0x2D, 0x30, 0x33, 0x36, +    0x3A, 0x3D, 0x40, 0x43, +    0x47, 0x4A, 0x4E, 0x51, +    0x55, 0x59, 0x5C, 0x60, +    0x64, 0x68, 0x6B, 0x6F, +    0x73, 0x77, 0x7B, 0x7F, +    0x83, 0x87, 0x8A, 0x8E, +    0x92, 0x96, 0x9A, 0x9E, +    0xA1, 0xA5, 0xA8, 0xAC, +    0xAF, 0xB3, 0xB6, 0xB9, +    0xBC, 0xBF, 0xC2, 0xC5, +    0xC7, 0xCA, 0xCC, 0xCE, +    0xD1, 0xD2, 0xD4, 0xD6, +    0xD7, 0xD9, 0xDA, 0xDB, +    0xDB, 0xDC, 0xDC, 0xDD, +    0xDD, 0xDC, 0xDC, 0xDC, +    0xDB, 0xDA, 0xD9, 0xD8, +    0xD7, 0xD5, 0xD3, 0xD2, +    0xD0, 0xCD, 0xCB, 0xC9, +    0xC6, 0xC3, 0xC1, 0xBE, +    0xBB, 0xB8, 0xB4, 0xB1, +    0xAE, 0xAA, 0xA7, 0xA3, +    0x9F, 0x9C, 0x98, 0x94, +    0x90, 0x8C, 0x89, 0x85, +    0x81, 0x7D, 0x79, 0x75, +    0x71, 0x6D, 0x69, 0x66, +    0x62, 0x5E, 0x5A, 0x57, +    0x53, 0x50, 0x4C, 0x49, +    0x45, 0x42, 0x3E, 0x3B, +    0x38, 0x35, 0x32, 0x2F, +    0x2C, 0x29, 0x26, 0x23 +#endif + +#if RGBLIGHT_BREATHE_TABLE_SIZE == 64 +    0x22, 0x28, +    0x2D, 0x33, +    0x3A, 0x40, +    0x47, 0x4E, +    0x55, 0x5C, +    0x64, 0x6B, +    0x73, 0x7B, +    0x83, 0x8A, +    0x92, 0x9A, +    0xA1, 0xA8, +    0xAF, 0xB6, +    0xBC, 0xC2, +    0xC7, 0xCC, +    0xD1, 0xD4, +    0xD7, 0xDA, +    0xDB, 0xDC, +    0xDD, 0xDC, +    0xDB, 0xD9, +    0xD7, 0xD3, +    0xD0, 0xCB, +    0xC6, 0xC1, +    0xBB, 0xB4, +    0xAE, 0xA7, +    0x9F, 0x98, +    0x90, 0x89, +    0x81, 0x79, +    0x71, 0x69, +    0x62, 0x5A, +    0x53, 0x4C, +    0x45, 0x3E, +    0x38, 0x32, +    0x2C, 0x26 +#endif +}; + +static const int table_scale = 256 / sizeof(rgblight_effect_breathe_table); diff --git a/quantum/rgblight/rgblight_list.h b/quantum/rgblight/rgblight_list.h new file mode 100644 index 0000000000..0fd68b75f3 --- /dev/null +++ b/quantum/rgblight/rgblight_list.h @@ -0,0 +1,136 @@ +/* Copyright 2018 Jack Humbert + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program.  If not, see <http://www.gnu.org/licenses/>. + */ +#pragma once + +#include "color.h" + +/* +######################################################################################## +##                                                                                    ## +##                                                                                    ## +##                                                                                    ## +##  The functions below have been deprecated and may be removed in a future release.  ## +##                                                                                    ## +##              Please use the values in color.h with the RGB functions.              ## +##                                                                                    ## +##                                                                                    ## +##                                                                                    ## +######################################################################################## +*/ + +/*                            SET RGB List                            */ +#define rgblight_setrgb_white() rgblight_setrgb(RGB_WHITE) +#define rgblight_setrgb_red() rgblight_setrgb(RGB_RED) +#define rgblight_setrgb_coral() rgblight_setrgb(RGB_CORAL) +#define rgblight_setrgb_orange() rgblight_setrgb(RGB_ORANGE) +#define rgblight_setrgb_goldenrod() rgblight_setrgb(RGB_GOLDENROD) +#define rgblight_setrgb_gold() rgblight_setrgb(RGB_GOLD) +#define rgblight_setrgb_yellow() rgblight_setrgb(RGB_YELLOW) +#define rgblight_setrgb_chartreuse() rgblight_setrgb(RGB_CHARTREUSE) +#define rgblight_setrgb_green() rgblight_setrgb(RGB_GREEN) +#define rgblight_setrgb_springgreen() rgblight_setrgb(RGB_SPRINGGREEN) +#define rgblight_setrgb_turquoise() rgblight_setrgb(RGB_TURQUOISE) +#define rgblight_setrgb_teal() rgblight_setrgb(RGB_TEAL) +#define rgblight_setrgb_cyan() rgblight_setrgb(RGB_CYAN) +#define rgblight_setrgb_azure() rgblight_setrgb(RGB_AZURE) +#define rgblight_setrgb_blue() rgblight_setrgb(RGB_BLUE) +#define rgblight_setrgb_purple() rgblight_setrgb(RGB_PURPLE) +#define rgblight_setrgb_magenta() rgblight_setrgb(RGB_MAGENTA) +#define rgblight_setrgb_pink() rgblight_setrgb(RGB_PINK) + +/*                            SET RGB List                            */ +#define rgblight_setrgb_white_at(at) rgblight_setrgb_at(RGB_WHITE, at) +#define rgblight_setrgb_red_at(at) rgblight_setrgb_at(RGB_RED, at) +#define rgblight_setrgb_coral_at(at) rgblight_setrgb_at(RGB_CORAL, at) +#define rgblight_setrgb_orange_at(at) rgblight_setrgb_at(RGB_ORANGE at) +#define rgblight_setrgb_goldenrod_at(at) rgblight_setrgb_at(RGB_GOLDENROD, at) +#define rgblight_setrgb_gold_at(at) rgblight_setrgb_at(RGB_GOLD, at) +#define rgblight_setrgb_yellow_at(at) rgblight_setrgb_at(RGB_YELLOW, at) +#define rgblight_setrgb_chartreuse_at(at) rgblight_setrgb_at(RGB_CHARTREUSE, at) +#define rgblight_setrgb_green_at(at) rgblight_setrgb_at(RGB_GREEN, at) +#define rgblight_setrgb_springgreen_at(at) rgblight_setrgb_at(RGB_SPRINGGREEN, at) +#define rgblight_setrgb_turquoise_at(at) rgblight_setrgb_at(RGB_TURQUOISE, at) +#define rgblight_setrgb_teal_at(at) rgblight_setrgb_at(RGB_TEAL, at) +#define rgblight_setrgb_cyan_at(at) rgblight_setrgb_at(RGB_CYAN, at) +#define rgblight_setrgb_azure_at(at) rgblight_setrgb_at(RGB_AZURE, at) +#define rgblight_setrgb_blue_at(at) rgblight_setrgb_at(RGB_BLUE, at) +#define rgblight_setrgb_purple_at(at) rgblight_setrgb_at(RGB_PURPLE, at) +#define rgblight_setrgb_magenta_at(at) rgblight_setrgb_at(RGB_MAGENTA, at) +#define rgblight_setrgb_pink_at(at) rgblight_setrgb_at(RGB_PINK, at) + +/*                            SET HSV List                            */ +#define rgblight_sethsv_white() rgblight_sethsv(HSV_WHITE) +#define rgblight_sethsv_red() rgblight_sethsv(HSV_RED) +#define rgblight_sethsv_coral() rgblight_sethsv(HSV_CORAL) +#define rgblight_sethsv_orange() rgblight_sethsv(HSV_ORANGE) +#define rgblight_sethsv_goldenrod() rgblight_sethsv(HSV_GOLDENROD) +#define rgblight_sethsv_gold() rgblight_sethsv(HSV_GOLD) +#define rgblight_sethsv_yellow() rgblight_sethsv(HSV_YELLOW) +#define rgblight_sethsv_chartreuse() rgblight_sethsv(HSV_CHARTREUSE) +#define rgblight_sethsv_green() rgblight_sethsv(HSV_GREEN) +#define rgblight_sethsv_springgreen() rgblight_sethsv(HSV_SPRINGGREEN) +#define rgblight_sethsv_turquoise() rgblight_sethsv(HSV_TURQUOISE) +#define rgblight_sethsv_teal() rgblight_sethsv(HSV_TEAL) +#define rgblight_sethsv_cyan() rgblight_sethsv(HSV_CYAN) +#define rgblight_sethsv_azure() rgblight_sethsv(HSV_AZURE) +#define rgblight_sethsv_blue() rgblight_sethsv(HSV_BLUE) +#define rgblight_sethsv_purple() rgblight_sethsv(HSV_PURPLE) +#define rgblight_sethsv_magenta() rgblight_sethsv(HSV_MAGENTA) +#define rgblight_sethsv_pink() rgblight_sethsv(HSV_PINK) + +/*                            SET HSV List                            */ +/*   If you're doing layer indication, this is best, as it won't      */ +/*   write to the eeprom, since it's limited (very high value).       */ +/*   If you want to use modes with this (since you can), then you     */ +/*   want to use rgblight_mode_noeeprom(x) instead.                   */ +#define rgblight_sethsv_noeeprom_white() rgblight_sethsv_noeeprom(HSV_WHITE) +#define rgblight_sethsv_noeeprom_red() rgblight_sethsv_noeeprom(HSV_RED) +#define rgblight_sethsv_noeeprom_coral() rgblight_sethsv_noeeprom(HSV_CORAL) +#define rgblight_sethsv_noeeprom_orange() rgblight_sethsv_noeeprom(HSV_ORANGE) +#define rgblight_sethsv_noeeprom_goldenrod() rgblight_sethsv_noeeprom(HSV_GOLDENROD) +#define rgblight_sethsv_noeeprom_gold() rgblight_sethsv_noeeprom(HSV_GOLD) +#define rgblight_sethsv_noeeprom_yellow() rgblight_sethsv_noeeprom(HSV_YELLOW) +#define rgblight_sethsv_noeeprom_chartreuse() rgblight_sethsv_noeeprom(HSV_CHARTREUSE) +#define rgblight_sethsv_noeeprom_green() rgblight_sethsv_noeeprom(HSV_GREEN) +#define rgblight_sethsv_noeeprom_springgreen() rgblight_sethsv_noeeprom(HSV_SPRINGGREEN) +#define rgblight_sethsv_noeeprom_turquoise() rgblight_sethsv_noeeprom(HSV_TURQUOISE) +#define rgblight_sethsv_noeeprom_teal() rgblight_sethsv_noeeprom(HSV_TEAL) +#define rgblight_sethsv_noeeprom_cyan() rgblight_sethsv_noeeprom(HSV_CYAN) +#define rgblight_sethsv_noeeprom_azure() rgblight_sethsv_noeeprom(HSV_AZURE) +#define rgblight_sethsv_noeeprom_blue() rgblight_sethsv_noeeprom(HSV_BLUE) +#define rgblight_sethsv_noeeprom_purple() rgblight_sethsv_noeeprom(HSV_PURPLE) +#define rgblight_sethsv_noeeprom_magenta() rgblight_sethsv_noeeprom(HSV_MAGENTA) +#define rgblight_sethsv_noeeprom_pink() rgblight_sethsv_noeeprom(HSV_PINK) + +/*                            SET HSV List                            */ +#define rgblight_sethsv_white_at(at) rgblight_sethsv_at(HSV_WHITE, at) +#define rgblight_sethsv_red_at(at) rgblight_sethsv_at(HSV_RED, at) +#define rgblight_sethsv_coral_at(at) rgblight_sethsv_at(HSV_CORAL, at) +#define rgblight_sethsv_orange_at(at) rgblight_sethsv_at(HSV_ORANGE, at) +#define rgblight_sethsv_goldenrod_at(at) rgblight_sethsv_at(HSV_GOLDENROD, at) +#define rgblight_sethsv_gold_at(at) rgblight_sethsv_at(HSV_GOLD, at) +#define rgblight_sethsv_yellow_at(at) rgblight_sethsv_at(HSV_YELLOW, at) +#define rgblight_sethsv_chartreuse_at(at) rgblight_sethsv_at(HSV_CHARTREUSE, at) +#define rgblight_sethsv_green_at(at) rgblight_sethsv_at(HSV_GREEN, at) +#define rgblight_sethsv_springgreen_at(at) rgblight_sethsv_at(HSV_SPRINGGREEN, at) +#define rgblight_sethsv_turquoise_at(at) rgblight_sethsv_at(HSV_TURQUOISE, at) +#define rgblight_sethsv_teal_at(at) rgblight_sethsv_at(HSV_TEAL, at) +#define rgblight_sethsv_cyan_at(at) rgblight_sethsv_at(HSV_CYAN, at) +#define rgblight_sethsv_azure_at(at) rgblight_sethsv_at(HSV_AZURE, at) +#define rgblight_sethsv_blue_at(at) rgblight_sethsv_at(HSV_BLUE, at) +#define rgblight_sethsv_purple_at(at) rgblight_sethsv_at(HSV_PURPLE, at) +#define rgblight_sethsv_magenta_at(at) rgblight_sethsv_at(HSV_MAGENTA, at) +#define rgblight_sethsv_pink_at(at) rgblight_sethsv_at(HSV_PINK, at) diff --git a/quantum/rgblight/rgblight_modes.h b/quantum/rgblight/rgblight_modes.h new file mode 100644 index 0000000000..7abdb87bc6 --- /dev/null +++ b/quantum/rgblight/rgblight_modes.h @@ -0,0 +1,75 @@ +#ifdef _RGBM_SINGLE_STATIC +_RGBM_SINGLE_STATIC(STATIC_LIGHT) +#    ifdef RGBLIGHT_EFFECT_BREATHING +_RGBM_MULTI_DYNAMIC(BREATHING) +_RGBM_TMP_DYNAMIC(breathing_3, BREATHING) +_RGBM_TMP_DYNAMIC(breathing_4, BREATHING) +_RGBM_TMP_DYNAMIC(BREATHING_end, BREATHING) +#    endif +#    ifdef RGBLIGHT_EFFECT_RAINBOW_MOOD +_RGBM_MULTI_DYNAMIC(RAINBOW_MOOD) +_RGBM_TMP_DYNAMIC(rainbow_mood_7, RAINBOW_MOOD) +_RGBM_TMP_DYNAMIC(RAINBOW_MOOD_end, RAINBOW_MOOD) +#    endif +#    ifdef RGBLIGHT_EFFECT_RAINBOW_SWIRL +_RGBM_MULTI_DYNAMIC(RAINBOW_SWIRL) +_RGBM_TMP_DYNAMIC(rainbow_swirl_10, RAINBOW_SWIRL) +_RGBM_TMP_DYNAMIC(rainbow_swirl_11, RAINBOW_SWIRL) +_RGBM_TMP_DYNAMIC(rainbow_swirl_12, RAINBOW_SWIRL) +_RGBM_TMP_DYNAMIC(rainbow_swirl_13, RAINBOW_SWIRL) +_RGBM_TMP_DYNAMIC(RAINBOW_SWIRL_end, RAINBOW_SWIRL) +#    endif +#    ifdef RGBLIGHT_EFFECT_SNAKE +_RGBM_MULTI_DYNAMIC(SNAKE) +_RGBM_TMP_DYNAMIC(snake_16, SNAKE) +_RGBM_TMP_DYNAMIC(snake_17, SNAKE) +_RGBM_TMP_DYNAMIC(snake_18, SNAKE) +_RGBM_TMP_DYNAMIC(snake_19, SNAKE) +_RGBM_TMP_DYNAMIC(SNAKE_end, SNAKE) +#    endif +#    ifdef RGBLIGHT_EFFECT_KNIGHT +_RGBM_MULTI_DYNAMIC(KNIGHT) +_RGBM_TMP_DYNAMIC(knight_22, KNIGHT) +_RGBM_TMP_DYNAMIC(KNIGHT_end, KNIGHT) +#    endif +#    ifdef RGBLIGHT_EFFECT_CHRISTMAS +_RGBM_SINGLE_DYNAMIC(CHRISTMAS) +#    endif +#    ifdef RGBLIGHT_EFFECT_STATIC_GRADIENT +_RGBM_MULTI_STATIC(STATIC_GRADIENT) +_RGBM_TMP_STATIC(static_gradient_26, STATIC_GRADIENT) +_RGBM_TMP_STATIC(static_gradient_27, STATIC_GRADIENT) +_RGBM_TMP_STATIC(static_gradient_28, STATIC_GRADIENT) +_RGBM_TMP_STATIC(static_gradient_29, STATIC_GRADIENT) +_RGBM_TMP_STATIC(static_gradient_30, STATIC_GRADIENT) +_RGBM_TMP_STATIC(static_gradient_31, STATIC_GRADIENT) +_RGBM_TMP_STATIC(static_gradient_32, STATIC_GRADIENT) +_RGBM_TMP_STATIC(static_gradient_33, STATIC_GRADIENT) +_RGBM_TMP_STATIC(STATIC_GRADIENT_end, STATIC_GRADIENT) +#    endif +#    ifdef RGBLIGHT_EFFECT_RGB_TEST +_RGBM_SINGLE_DYNAMIC(RGB_TEST) +#    endif +#    ifdef RGBLIGHT_EFFECT_ALTERNATING +_RGBM_SINGLE_DYNAMIC(ALTERNATING) +#    endif +#    ifdef RGBLIGHT_EFFECT_TWINKLE +_RGBM_MULTI_DYNAMIC(TWINKLE) +_RGBM_TMP_DYNAMIC(twinkle_38, TWINKLE) +_RGBM_TMP_DYNAMIC(twinkle_39, TWINKLE) +_RGBM_TMP_DYNAMIC(twinkle_40, TWINKLE) +_RGBM_TMP_DYNAMIC(twinkle_41, TWINKLE) +_RGBM_TMP_DYNAMIC(TWINKLE_end, TWINKLE) +#    endif +////  Add a new mode here. +// #ifdef RGBLIGHT_EFFECT_<name> +//    _RGBM_<SINGLE|MULTI>_<STATIC|DYNAMIC>( <name> ) +// #endif +#endif + +#undef _RGBM_SINGLE_STATIC +#undef _RGBM_SINGLE_DYNAMIC +#undef _RGBM_MULTI_STATIC +#undef _RGBM_MULTI_DYNAMIC +#undef _RGBM_TMP_STATIC +#undef _RGBM_TMP_DYNAMIC diff --git a/quantum/rgblight/rgblight_post_config.h b/quantum/rgblight/rgblight_post_config.h new file mode 100644 index 0000000000..3c14cb6109 --- /dev/null +++ b/quantum/rgblight/rgblight_post_config.h @@ -0,0 +1,5 @@ +#if defined(RGBLED_SPLIT) && !defined(RGBLIGHT_SPLIT) +// When RGBLED_SPLIT is defined, +// it is considered that RGBLIGHT_SPLIT is defined implicitly. +#    define RGBLIGHT_SPLIT +#endif | 
