diff options
-rw-r--r-- | quantum/rgblight.c | 71 | ||||
-rw-r--r-- | quantum/rgblight.h | 46 |
2 files changed, 109 insertions, 8 deletions
diff --git a/quantum/rgblight.c b/quantum/rgblight.c index acebde876d..6ae185fea8 100644 --- a/quantum/rgblight.c +++ b/quantum/rgblight.c @@ -38,17 +38,23 @@ # include "velocikey.h" #endif +#ifndef MIN +# define MIN(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 @@ -97,6 +103,10 @@ LED_TYPE led[RGBLED_NUM]; # define LED_ARRAY led #endif +#ifdef RGBLIGHT_LAYERS +rgblight_segment_t const *const *rgblight_layers = NULL; +#endif + static uint8_t clipping_start_pos = 0; static uint8_t clipping_num_leds = RGBLED_NUM; static uint8_t effect_start_pos = 0; @@ -604,11 +614,67 @@ void rgblight_sethsv_master(uint8_t hue, uint8_t sat, uint8_t val) { rgblight_se 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) { + uint8_t mask = 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); + } +} + +bool rgblight_get_layer_state(uint8_t layer) { + uint8_t mask = 1 << layer; + return (rgblight_status.enabled_layer_mask & mask) != 0; +} + +// Write any enabled LED layers into the buffer +static void rgblight_layers_write(void) { + 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++) { + sethsv(segment.hue, segment.sat, segment.val, led_ptr); + } + segment_ptr++; + } + } +} +#endif + #ifndef RGBLIGHT_CUSTOM_DRIVER void rgblight_set(void) { LED_TYPE *start_led; uint16_t num_leds = clipping_num_leds; +# ifdef RGBLIGHT_LAYERS + if (rgblight_layers != NULL) { + rgblight_layers_write(); + } +# endif + if (!rgblight_config.enable) { for (uint8_t i = effect_start_pos; i < effect_end_pos; i++) { led[i].r = 0; @@ -651,6 +717,11 @@ 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) { +# 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(); diff --git a/quantum/rgblight.h b/quantum/rgblight.h index 39c4c2784f..97882c5b29 100644 --- a/quantum/rgblight.h +++ b/quantum/rgblight.h @@ -170,6 +170,32 @@ enum RGBLIGHT_EFFECT_MODE { # include <avr/pgmspace.h> # endif +# 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 } +# define RGBLIGHT_MAX_LAYERS 8 +# 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; +# endif + extern LED_TYPE led[RGBLED_NUM]; extern const uint8_t RGBLED_BREATHING_INTERVALS[4] PROGMEM; @@ -199,6 +225,9 @@ typedef struct _rgblight_status_t { # ifdef RGBLIGHT_SPLIT uint8_t change_flags; # endif +# ifdef RGBLIGHT_LAYERS + uint8_t enabled_layer_mask; +# endif } rgblight_status_t; /* === Utility Functions ===*/ @@ -294,25 +323,26 @@ 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 +# 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 +# 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; |