diff options
-rw-r--r-- | build_keyboard.mk | 18 | ||||
-rw-r--r-- | changelog.md | 1 | ||||
-rw-r--r-- | common_features.mk | 2 | ||||
-rw-r--r-- | quantum/rgblight.c | 390 | ||||
-rw-r--r-- | quantum/rgblight.h | 134 | ||||
-rw-r--r-- | quantum/rgblight_modes.h | 67 | ||||
-rw-r--r-- | quantum/rgblight_post_config.h | 5 | ||||
-rw-r--r-- | quantum/split_common/post_config.h | 15 | ||||
-rw-r--r-- | quantum/split_common/transport.c | 184 |
9 files changed, 534 insertions, 282 deletions
diff --git a/build_keyboard.mk b/build_keyboard.mk index ee6a69fc79..5d633f2716 100644 --- a/build_keyboard.mk +++ b/build_keyboard.mk @@ -280,6 +280,23 @@ ifneq ("$(wildcard $(KEYBOARD_PATH_1)/config.h)","") CONFIG_H += $(KEYBOARD_PATH_1)/config.h endif +POST_CONFIG_H := +ifneq ("$(wildcard $(KEYBOARD_PATH_1)/post_config.h)","") + POST_CONFIG_H += $(KEYBOARD_PATH_1)/post_config.h +endif +ifneq ("$(wildcard $(KEYBOARD_PATH_2)/post_config.h)","") + POST_CONFIG_H += $(KEYBOARD_PATH_2)/post_config.h +endif +ifneq ("$(wildcard $(KEYBOARD_PATH_3)/post_config.h)","") + POST_CONFIG_H += $(KEYBOARD_PATH_3)/post_config.h +endif +ifneq ("$(wildcard $(KEYBOARD_PATH_4)/post_config.h)","") + POST_CONFIG_H += $(KEYBOARD_PATH_4)/post_config.h +endif +ifneq ("$(wildcard $(KEYBOARD_PATH_5)/post_config.h)","") + POST_CONFIG_H += $(KEYBOARD_PATH_5)/post_config.h +endif + # Save the defines and includes here, so we don't include any keymap specific ones PROJECT_DEFS := $(OPT_DEFS) PROJECT_INC := $(VPATH) $(EXTRAINCDIRS) $(KEYBOARD_PATHS) @@ -355,6 +372,7 @@ ifeq ($(strip $(VISUALIZER_ENABLE)), yes) include $(VISUALIZER_PATH)/visualizer.mk endif +CONFIG_H += $(POST_CONFIG_H) ALL_CONFIGS := $(PROJECT_CONFIG) $(CONFIG_H) OUTPUTS := $(KEYMAP_OUTPUT) $(KEYBOARD_OUTPUT) diff --git a/changelog.md b/changelog.md index c2645bb2aa..3ea76a5879 100644 --- a/changelog.md +++ b/changelog.md @@ -5,3 +5,4 @@ 04-16-2019 - Fix info.json for Ergodox EZ 04-16-2019 - Add support for WS2812 based RGB Matrix 04-18-2019 - Fix Eager Per Row Debouncing bug +04-22-2019 - Add Split RGB support diff --git a/common_features.mk b/common_features.mk index bd1685869d..eb623d18fa 100644 --- a/common_features.mk +++ b/common_features.mk @@ -103,6 +103,7 @@ ifeq ($(strip $(UNICODE_COMMON)), yes) endif ifeq ($(strip $(RGBLIGHT_ENABLE)), yes) + POST_CONFIG_H += $(QUANTUM_DIR)/rgblight_post_config.h OPT_DEFS += -DRGBLIGHT_ENABLE SRC += $(QUANTUM_DIR)/rgblight.c CIE1931_CURVE = yes @@ -318,6 +319,7 @@ ifneq ($(strip $(DEBOUNCE_TYPE)), custom) endif ifeq ($(strip $(SPLIT_KEYBOARD)), yes) + POST_CONFIG_H += $(QUANTUM_DIR)/split_common/post_config.h OPT_DEFS += -DSPLIT_KEYBOARD # Include files used by all split keyboards diff --git a/quantum/rgblight.c b/quantum/rgblight.c index e2410424e4..5ec11bc077 100644 --- a/quantum/rgblight.c +++ b/quantum/rgblight.c @@ -34,14 +34,38 @@ #include "velocikey.h" #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_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_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) RGBLIGHT_MODE_ ## sym, -#define _RGBM_TMP_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.h" +#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" }; static inline int is_static_effect(uint8_t mode) { @@ -61,14 +85,18 @@ const uint16_t RGBLED_GRADIENT_RANGES[] PROGMEM = {360, 240, 180, 120, 90}; #endif rgblight_config_t rgblight_config; +rgblight_status_t rgblight_status = { .timer_enabled = false }; bool is_rgblight_initialized = false; +#ifdef RGBLIGHT_USE_TIMER +animation_status_t animation_status = {}; +#endif + #ifndef LED_ARRAY LED_TYPE led[RGBLED_NUM]; #define LED_ARRAY led #endif -bool rgblight_timer_enabled = false; static uint8_t clipping_start_pos = 0; static uint8_t clipping_num_leds = RGBLED_NUM; @@ -221,6 +249,7 @@ void rgblight_init(void) { eeconfig_update_rgblight_default(); } rgblight_config.raw = eeconfig_read_rgblight(); + RGBLIGHT_SPLIT_SET_CHANGE_HSVS; if (!rgblight_config.mode) { dprintf("rgblight_init rgblight_config.mode = 0. Write default values to EEPROM.\n"); eeconfig_update_rgblight_default(); @@ -321,6 +350,7 @@ void rgblight_mode_eeprom_helper(uint8_t mode, bool write_to_eeprom) { } else { rgblight_config.mode = mode; } + RGBLIGHT_SPLIT_SET_CHANGE_MODE; if (write_to_eeprom) { eeconfig_update_rgblight(rgblight_config.raw); xprintf("rgblight mode [EEPROM]: %u\n", rgblight_config.mode); @@ -336,6 +366,9 @@ void rgblight_mode_eeprom_helper(uint8_t mode, bool write_to_eeprom) { rgblight_timer_enable(); #endif } +#ifdef RGBLIGHT_USE_TIMER + animation_status.restart = true; +#endif rgblight_sethsv_noeeprom(rgblight_config.hue, rgblight_config.sat, rgblight_config.val); } @@ -389,6 +422,7 @@ void rgblight_disable(void) { #ifdef RGBLIGHT_USE_TIMER rgblight_timer_disable(); #endif + RGBLIGHT_SPLIT_SET_CHANGE_MODE; wait_ms(50); rgblight_set(); } @@ -399,6 +433,7 @@ void rgblight_disable_noeeprom(void) { #ifdef RGBLIGHT_USE_TIMER rgblight_timer_disable(); #endif + RGBLIGHT_SPLIT_SET_CHANGE_MODE; wait_ms(50); rgblight_set(); } @@ -505,11 +540,13 @@ void rgblight_decrease_val(void) { } void rgblight_increase_speed(void) { rgblight_config.speed = increment( rgblight_config.speed, 1, 0, 3 ); + //RGBLIGHT_SPLIT_SET_CHANGE_HSVS; // NEED? eeconfig_update_rgblight(rgblight_config.raw);//EECONFIG needs to be increased to support this } void rgblight_decrease_speed(void) { rgblight_config.speed = decrement( rgblight_config.speed, 1, 0, 3 ); + //RGBLIGHT_SPLIT_SET_CHANGE_HSVS; // NEED?? eeconfig_update_rgblight(rgblight_config.raw);//EECONFIG needs to be increased to support this } @@ -524,6 +561,7 @@ void rgblight_sethsv_noeeprom_old(uint16_t hue, uint8_t sat, uint8_t val) { void rgblight_sethsv_eeprom_helper(uint16_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; @@ -534,33 +572,30 @@ void rgblight_sethsv_eeprom_helper(uint16_t hue, uint8_t sat, uint8_t val, bool if ( 1 == 0 ) { //dummy } #ifdef RGBLIGHT_EFFECT_BREATHING - else if (rgblight_config.mode >= RGBLIGHT_MODE_BREATHING && - rgblight_config.mode <= RGBLIGHT_MODE_BREATHING_end) { + 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_config.mode >= RGBLIGHT_MODE_RAINBOW_MOOD && - rgblight_config.mode <= RGBLIGHT_MODE_RAINBOW_MOOD_end) { + 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_config.mode >= RGBLIGHT_MODE_RAINBOW_SWIRL && - rgblight_config.mode <= RGBLIGHT_MODE_RAINBOW_SWIRL_end) { + 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_config.mode >= RGBLIGHT_MODE_STATIC_GRADIENT && - rgblight_config.mode <= RGBLIGHT_MODE_STATIC_GRADIENT_end) { + else if (rgblight_status.base_mode == RGBLIGHT_MODE_STATIC_GRADIENT) { // static gradient uint16_t _hue; - int8_t direction = ((rgblight_config.mode - RGBLIGHT_MODE_STATIC_GRADIENT) % 2) ? -1 : 1; - uint16_t range = pgm_read_word(&RGBLED_GRADIENT_RANGES[(rgblight_config.mode - RGBLIGHT_MODE_STATIC_GRADIENT) / 2]); + uint8_t delta = rgblight_config.mode - rgblight_status.base_mode; + int8_t direction = (delta % 2) ? -1 : 1; + uint16_t range = pgm_read_word(&RGBLED_GRADIENT_RANGES[delta / 2]); for (uint8_t i = 0; i < RGBLED_NUM; i++) { _hue = (range / RGBLED_NUM * i * direction + hue + 360) % 360; dprintf("rgblight rainbow set hsv: %u,%u,%d,%u\n", i, _hue, direction, range); @@ -570,6 +605,13 @@ void rgblight_sethsv_eeprom_helper(uint16_t hue, uint8_t sat, uint8_t val, bool } #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; @@ -711,10 +753,59 @@ void rgblight_set(void) { } #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) { + 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 -// Animation timer -- AVR Timer3 +typedef void (*effect_func_t)(animation_status_t *anim); + +// Animation timer -- use system timer (AVR Timer0) void rgblight_timer_init(void) { + // OLD!!!! Animation timer -- AVR Timer3 // static uint8_t rgblight_timer_is_init = 0; // if (rgblight_timer_is_init) { // return; @@ -730,19 +821,29 @@ void rgblight_timer_init(void) { // OCR3AL = RGBLED_TIMER_TOP & 0xff; // SREG = sreg; - rgblight_timer_enabled = true; + rgblight_status.timer_enabled = false; + RGBLIGHT_SPLIT_SET_CHANGE_TIMER_ENABLE; } void rgblight_timer_enable(void) { - rgblight_timer_enabled = true; - dprintf("TIMER3 enabled.\n"); + if( !is_static_effect(rgblight_config.mode) ) { + rgblight_status.timer_enabled = true; + } + animation_status.last_timer = timer_read(); + RGBLIGHT_SPLIT_SET_CHANGE_TIMER_ENABLE; + dprintf("rgblight timer enabled.\n"); } void rgblight_timer_disable(void) { - rgblight_timer_enabled = false; - dprintf("TIMER3 disabled.\n"); + rgblight_status.timer_enabled = false; + RGBLIGHT_SPLIT_SET_CHANGE_TIMER_ENABLE; + dprintf("rgblight timer disable.\n"); } void rgblight_timer_toggle(void) { - rgblight_timer_enabled ^= rgblight_timer_enabled; - dprintf("TIMER3 toggled.\n"); + 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) { @@ -751,64 +852,116 @@ void rgblight_show_solid_color(uint8_t r, uint8_t g, uint8_t b) { 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; - if (rgblight_timer_enabled) { // static light mode, do nothing here if ( 1 == 0 ) { //dummy } #ifdef RGBLIGHT_EFFECT_BREATHING - else if (rgblight_config.mode >= RGBLIGHT_MODE_BREATHING && - rgblight_config.mode <= RGBLIGHT_MODE_BREATHING_end) { + else if (rgblight_status.base_mode == RGBLIGHT_MODE_BREATHING) { // breathing mode - rgblight_effect_breathing(rgblight_config.mode - RGBLIGHT_MODE_BREATHING ); + 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_config.mode >= RGBLIGHT_MODE_RAINBOW_MOOD && - rgblight_config.mode <= RGBLIGHT_MODE_RAINBOW_MOOD_end) { + else if (rgblight_status.base_mode == RGBLIGHT_MODE_RAINBOW_MOOD) { // rainbow mood mode - rgblight_effect_rainbow_mood(rgblight_config.mode - RGBLIGHT_MODE_RAINBOW_MOOD); + 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_config.mode >= RGBLIGHT_MODE_RAINBOW_SWIRL && - rgblight_config.mode <= RGBLIGHT_MODE_RAINBOW_SWIRL_end) { + else if (rgblight_status.base_mode == RGBLIGHT_MODE_RAINBOW_SWIRL) { // rainbow swirl mode - rgblight_effect_rainbow_swirl(rgblight_config.mode - RGBLIGHT_MODE_RAINBOW_SWIRL); + 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_config.mode >= RGBLIGHT_MODE_SNAKE && - rgblight_config.mode <= RGBLIGHT_MODE_SNAKE_end) { + else if (rgblight_status.base_mode == RGBLIGHT_MODE_SNAKE) { // snake mode - rgblight_effect_snake(rgblight_config.mode - RGBLIGHT_MODE_SNAKE); + 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_config.mode >= RGBLIGHT_MODE_KNIGHT && - rgblight_config.mode <= RGBLIGHT_MODE_KNIGHT_end) { + else if (rgblight_status.base_mode == RGBLIGHT_MODE_KNIGHT) { // knight mode - rgblight_effect_knight(rgblight_config.mode - RGBLIGHT_MODE_KNIGHT); + interval_time = get_interval_time(&RGBLED_KNIGHT_INTERVALS[delta], 5, 100); + effect_func = rgblight_effect_knight; } #endif #ifdef RGBLIGHT_EFFECT_CHRISTMAS - else if (rgblight_config.mode == RGBLIGHT_MODE_CHRISTMAS) { + else if (rgblight_status.base_mode == RGBLIGHT_MODE_CHRISTMAS) { // christmas mode - rgblight_effect_christmas(); + interval_time = RGBLIGHT_EFFECT_CHRISTMAS_INTERVAL; + effect_func = (effect_func_t)rgblight_effect_christmas; } #endif #ifdef RGBLIGHT_EFFECT_RGB_TEST - else if (rgblight_config.mode == RGBLIGHT_MODE_RGB_TEST) { + else if (rgblight_status.base_mode == RGBLIGHT_MODE_RGB_TEST) { // RGB test mode - rgblight_effect_rgbtest(); + 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_config.mode == RGBLIGHT_MODE_ALTERNATING){ - rgblight_effect_alternating(); + else if (rgblight_status.base_mode == RGBLIGHT_MODE_ALTERNATING){ + interval_time = 500; + effect_func = (effect_func_t)rgblight_effect_alternating; + } +#endif + if (animation_status.restart) { + animation_status.restart = false; + animation_status.last_timer = timer_read() - interval_time - 1; + animation_status.pos16 = 0; // restart signal to local each effect } + if (timer_elapsed(animation_status.last_timer) >= interval_time) { +#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; + //dprintf("rgblight animation tick\n"); + if (timer_elapsed(report_last_timer) >= 30000) { + report_last_timer = timer_read(); + dprintf("rgblight animation tick report to slave\n"); + RGBLIGHT_SPLIT_ANIMATION_TICK; + } + } + oldpos16 = animation_status.pos16; + //dprintf("call effect function\n"); +#endif + animation_status.last_timer += interval_time; + effect_func(&animation_status); +#if defined(RGBLIGHT_SPLIT) && !defined(RGBLIGHT_SPLIT_NO_ANIMATION_SYNC) + //dprintf("pos16, oldpos16 = %d %d\n", + // animation_status.pos16,oldpos16); + if (animation_status.pos16 == 0 && oldpos16 != 0) { + //dprintf("flag on\n"); + tick_flag = true; + } #endif + } } } @@ -819,22 +972,13 @@ void rgblight_task(void) { __attribute__ ((weak)) const uint8_t RGBLED_BREATHING_INTERVALS[] PROGMEM = {30, 20, 10, 5}; -void rgblight_effect_breathing(uint8_t interval) { - static uint8_t pos = 0; - static uint16_t last_timer = 0; +void rgblight_effect_breathing(animation_status_t *anim) { float val; - uint8_t interval_time = get_interval_time(&RGBLED_BREATHING_INTERVALS[interval], 1, 100); - - if (timer_elapsed(last_timer) < interval_time) { - return; - } - last_timer = timer_read(); - // http://sean.voisen.org/blog/2011/10/breathing-led-with-arduino/ - val = (exp(sin((pos/255.0)*M_PI)) - RGBLIGHT_EFFECT_BREATHE_CENTER/M_E)*(RGBLIGHT_EFFECT_BREATHE_MAX/(M_E-1/M_E)); + val = (exp(sin((anim->pos/255.0)*M_PI)) - RGBLIGHT_EFFECT_BREATHE_CENTER/M_E)*(RGBLIGHT_EFFECT_BREATHE_MAX/(M_E-1/M_E)); rgblight_sethsv_noeeprom_old(rgblight_config.hue, rgblight_config.sat, val); - pos = (pos + 1) % 256; + anim->pos = (anim->pos + 1) % 256; } #endif @@ -842,18 +986,9 @@ void rgblight_effect_breathing(uint8_t interval) { __attribute__ ((weak)) const uint8_t RGBLED_RAINBOW_MOOD_INTERVALS[] PROGMEM = {120, 60, 30}; -void rgblight_effect_rainbow_mood(uint8_t interval) { - static uint16_t current_hue = 0; - static uint16_t last_timer = 0; - - uint8_t interval_time = get_interval_time(&RGBLED_RAINBOW_MOOD_INTERVALS[interval], 5, 100); - - if (timer_elapsed(last_timer) < interval_time) { - return; - } - last_timer = timer_read(); - rgblight_sethsv_noeeprom_old(current_hue, rgblight_config.sat, rgblight_config.val); - current_hue = (current_hue + 1) % 360; +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 = (anim->current_hue + 1) % 360; } #endif @@ -865,31 +1000,23 @@ void rgblight_effect_rainbow_mood(uint8_t interval) { __attribute__ ((weak)) const uint8_t RGBLED_RAINBOW_SWIRL_INTERVALS[] PROGMEM = {100, 50, 20}; -void rgblight_effect_rainbow_swirl(uint8_t interval) { - static uint16_t current_hue = 0; - static uint16_t last_timer = 0; +void rgblight_effect_rainbow_swirl(animation_status_t *anim) { uint16_t hue; uint8_t i; - uint8_t interval_time = get_interval_time(&RGBLED_RAINBOW_SWIRL_INTERVALS[interval / 2], 1, 100); - - if (timer_elapsed(last_timer) < interval_time) { - return; - } - last_timer = timer_read(); for (i = 0; i < RGBLED_NUM; i++) { - hue = (RGBLIGHT_RAINBOW_SWIRL_RANGE / RGBLED_NUM * i + current_hue) % 360; + hue = (RGBLIGHT_RAINBOW_SWIRL_RANGE / RGBLED_NUM * i + anim->current_hue) % 360; sethsv(hue, rgblight_config.sat, rgblight_config.val, (LED_TYPE *)&led[i]); } rgblight_set(); - if (interval % 2) { - current_hue = (current_hue + 1) % 360; + if (anim->delta % 2) { + anim->current_hue = (anim->current_hue + 1) % 360; } else { - if (current_hue - 1 < 0) { - current_hue = 359; + if (anim->current_hue - 1 < 0) { + anim->current_hue = 359; } else { - current_hue = current_hue - 1; + anim->current_hue = anim->current_hue - 1; } } } @@ -899,22 +1026,27 @@ void rgblight_effect_rainbow_swirl(uint8_t interval) { __attribute__ ((weak)) const uint8_t RGBLED_SNAKE_INTERVALS[] PROGMEM = {100, 50, 20}; -void rgblight_effect_snake(uint8_t interval) { +void rgblight_effect_snake(animation_status_t *anim) { static uint8_t pos = 0; - static uint16_t last_timer = 0; uint8_t i, j; int8_t k; int8_t increment = 1; - if (interval % 2) { + + if (anim->delta % 2) { increment = -1; } - uint8_t interval_time = get_interval_time(&RGBLED_SNAKE_INTERVALS[interval / 2], 1, 200); - - if (timer_elapsed(last_timer) < interval_time) { - return; +#if defined(RGBLIGHT_SPLIT) && !defined(RGBLIGHT_SPLIT_NO_ANIMATION_SYNC) + if (anim->pos == 0) { // restart signal + if (increment == 1) { + pos = RGBLED_NUM - 1; + } else { + pos = 0; + } + anim->pos = 1; } - last_timer = timer_read(); +#endif + for (i = 0; i < RGBLED_NUM; i++) { led[i].r = 0; led[i].g = 0; @@ -925,7 +1057,9 @@ void rgblight_effect_snake(uint8_t interval) { k = k + RGBLED_NUM; } if (i == k) { - sethsv(rgblight_config.hue, rgblight_config.sat, (uint8_t)(rgblight_config.val*(RGBLIGHT_EFFECT_SNAKE_LENGTH-j)/RGBLIGHT_EFFECT_SNAKE_LENGTH), (LED_TYPE *)&led[i]); + sethsv(rgblight_config.hue, rgblight_config.sat, + (uint8_t)(rgblight_config.val*(RGBLIGHT_EFFECT_SNAKE_LENGTH-j)/RGBLIGHT_EFFECT_SNAKE_LENGTH), + (LED_TYPE *)&led[i]); } } } @@ -933,11 +1067,20 @@ void rgblight_effect_snake(uint8_t interval) { if (increment == 1) { if (pos - 1 < 0) { pos = RGBLED_NUM - 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) % RGBLED_NUM; +#if defined(RGBLIGHT_SPLIT) && !defined(RGBLIGHT_SPLIT_NO_ANIMATION_SYNC) + anim->pos = pos; +#endif } } #endif @@ -946,21 +1089,21 @@ void rgblight_effect_snake(uint8_t interval) { __attribute__ ((weak)) const uint8_t RGBLED_KNIGHT_INTERVALS[] PROGMEM = {127, 63, 31}; -void rgblight_effect_knight(uint8_t interval) { - static uint16_t last_timer = 0; - - uint8_t interval_time = get_interval_time(&RGBLED_KNIGHT_INTERVALS[interval], 5, 100); - - if (timer_elapsed(last_timer) < interval_time) { - return; - } - last_timer = timer_read(); +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 = 0; i < RGBLED_NUM; i++) { led[i].r = 0; @@ -988,23 +1131,23 @@ void rgblight_effect_knight(uint8_t interval) { 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 -void rgblight_effect_christmas(void) { - static uint16_t current_offset = 0; - static uint16_t last_timer = 0; +void rgblight_effect_christmas(animation_status_t *anim) { uint16_t hue; uint8_t i; - if (timer_elapsed(last_timer) < RGBLIGHT_EFFECT_CHRISTMAS_INTERVAL) { - return; - } - last_timer = timer_read(); - current_offset = (current_offset + 1) % 2; + + anim->current_offset = (anim->current_offset + 1) % 2; for (i = 0; i < RGBLED_NUM; i++) { - hue = 0 + ((i/RGBLIGHT_EFFECT_CHRISTMAS_STEP + current_offset) % 2) * 120; + hue = 0 + ((i/RGBLIGHT_EFFECT_CHRISTMAS_STEP + anim->current_offset) % 2) * 120; sethsv(hue, rgblight_config.sat, rgblight_config.val, (LED_TYPE *)&led[i]); } rgblight_set(); @@ -1015,52 +1158,39 @@ void rgblight_effect_christmas(void) { __attribute__ ((weak)) const uint16_t RGBLED_RGBTEST_INTERVALS[] PROGMEM = {1024}; -void rgblight_effect_rgbtest(void) { - static uint8_t pos = 0; - static uint16_t last_timer = 0; +void rgblight_effect_rgbtest(animation_status_t *anim) { static uint8_t maxval = 0; uint8_t g; uint8_t r; uint8_t b; - if (timer_elapsed(last_timer) < pgm_read_word(&RGBLED_RGBTEST_INTERVALS[0])) { - return; - } - if( maxval == 0 ) { LED_TYPE tmp_led; sethsv(0, 255, RGBLIGHT_LIMIT_VAL, &tmp_led); maxval = tmp_led.r; } - last_timer = timer_read(); g = r = b = 0; - switch( pos ) { + switch( anim->pos ) { case 0: r = maxval; break; case 1: g = maxval; break; case 2: b = maxval; break; } rgblight_setrgb(r, g, b); - pos = (pos + 1) % 3; + anim->pos = (anim->pos + 1) % 3; } #endif #ifdef RGBLIGHT_EFFECT_ALTERNATING -void rgblight_effect_alternating(void){ - static uint16_t last_timer = 0; - static uint16_t pos = 0; - if (timer_elapsed(last_timer) < 500) { - return; - } - last_timer = timer_read(); +void rgblight_effect_alternating(animation_status_t *anim) { for(int i = 0; i<RGBLED_NUM; i++){ - if(i<RGBLED_NUM/2 && pos){ + if(i<RGBLED_NUM/2 && anim->pos){ sethsv(rgblight_config.hue, rgblight_config.sat, rgblight_config.val, (LED_TYPE *)&led[i]); - }else if (i>=RGBLED_NUM/2 && !pos){ + }else if (i>=RGBLED_NUM/2 && !anim->pos){ sethsv(rgblight_config.hue, rgblight_config.sat, rgblight_config.val, (LED_TYPE *)&led[i]); }else{ sethsv(rgblight_config.hue, rgblight_config.sat, 0, (LED_TYPE *)&led[i]); } } rgblight_set(); - pos = (pos + 1) % 2; + anim->pos = (anim->pos + 1) % 2; } #endif diff --git a/quantum/rgblight.h b/quantum/rgblight.h index 1769f719d9..748d009dcf 100644 --- a/quantum/rgblight.h +++ b/quantum/rgblight.h @@ -68,11 +68,11 @@ #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) RGBLIGHT_MODE_ ## sym, -#define _RGBM_TMP_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.h" +#include "rgblight_modes.h" RGBLIGHT_MODE_last }; @@ -163,6 +163,33 @@ typedef union { }; } rgblight_config_t; +typedef struct _rgblight_status_t { + uint8_t base_mode; + bool timer_enabled; +#ifdef RGBLIGHT_SPLIT + uint8_t change_flags; +#endif +} rgblight_status_t; + +#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) + + 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 + void rgblight_init(void); void rgblight_increase(void); void rgblight_decrease(void); @@ -237,82 +264,33 @@ void rgblight_timer_init(void); void rgblight_timer_enable(void); void rgblight_timer_disable(void); void rgblight_timer_toggle(void); -void rgblight_effect_breathing(uint8_t interval); -void rgblight_effect_rainbow_mood(uint8_t interval); -void rgblight_effect_rainbow_swirl(uint8_t interval); -void rgblight_effect_snake(uint8_t interval); -void rgblight_effect_knight(uint8_t interval); -void rgblight_effect_christmas(void); -void rgblight_effect_rgbtest(void); -void rgblight_effect_alternating(void); -#endif // #ifndef RGBLIGHT_H_DUMMY_DEFINE -#endif // RGBLIGHT_H +#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; + int16_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); -#ifdef _RGBM_SINGLE_STATIC - _RGBM_SINGLE_STATIC( STATIC_LIGHT ) - #ifdef RGBLIGHT_EFFECT_BREATHING - _RGBM_MULTI_DYNAMIC( BREATHING ) - _RGBM_TMP_DYNAMIC( breathing_3 ) - _RGBM_TMP_DYNAMIC( breathing_4 ) - _RGBM_TMP_DYNAMIC( BREATHING_end ) - #endif - #ifdef RGBLIGHT_EFFECT_RAINBOW_MOOD - _RGBM_MULTI_DYNAMIC( RAINBOW_MOOD ) - _RGBM_TMP_DYNAMIC( rainbow_mood_7 ) - _RGBM_TMP_DYNAMIC( RAINBOW_MOOD_end ) - #endif - #ifdef RGBLIGHT_EFFECT_RAINBOW_SWIRL - _RGBM_MULTI_DYNAMIC( RAINBOW_SWIRL ) - _RGBM_TMP_DYNAMIC( rainbow_swirl_10 ) - _RGBM_TMP_DYNAMIC( rainbow_swirl_11 ) - _RGBM_TMP_DYNAMIC( rainbow_swirl_12 ) - _RGBM_TMP_DYNAMIC( rainbow_swirl_13 ) - _RGBM_TMP_DYNAMIC( RAINBOW_SWIRL_end ) - #endif - #ifdef RGBLIGHT_EFFECT_SNAKE - _RGBM_MULTI_DYNAMIC( SNAKE ) - _RGBM_TMP_DYNAMIC( snake_16 ) - _RGBM_TMP_DYNAMIC( snake_17 ) - _RGBM_TMP_DYNAMIC( snake_18 ) - _RGBM_TMP_DYNAMIC( snake_19 ) - _RGBM_TMP_DYNAMIC( SNAKE_end ) - #endif - #ifdef RGBLIGHT_EFFECT_KNIGHT - _RGBM_MULTI_DYNAMIC( KNIGHT ) - _RGBM_TMP_DYNAMIC( knight_22 ) - _RGBM_TMP_DYNAMIC( KNIGHT_end ) - #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 ) - _RGBM_TMP_STATIC( static_gradient_27 ) - _RGBM_TMP_STATIC( static_gradient_28 ) - _RGBM_TMP_STATIC( static_gradient_29 ) - _RGBM_TMP_STATIC( static_gradient_30 ) - _RGBM_TMP_STATIC( static_gradient_31 ) - _RGBM_TMP_STATIC( static_gradient_32 ) - _RGBM_TMP_STATIC( static_gradient_33 ) - _RGBM_TMP_STATIC( STATIC_GRADIENT_end ) - #endif - #ifdef RGBLIGHT_EFFECT_RGB_TEST - _RGBM_SINGLE_DYNAMIC( RGB_TEST ) - #endif - #ifdef RGBLIGHT_EFFECT_ALTERNATING - _RGBM_SINGLE_DYNAMIC( ALTERNATING ) - #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 +#endif // #ifndef RGBLIGHT_H_DUMMY_DEFINE +#endif // RGBLIGHT_H diff --git a/quantum/rgblight_modes.h b/quantum/rgblight_modes.h new file mode 100644 index 0000000000..8a8f9bdda9 --- /dev/null +++ b/quantum/rgblight_modes.h @@ -0,0 +1,67 @@ +#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 + //// 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_post_config.h b/quantum/rgblight_post_config.h new file mode 100644 index 0000000000..048746c4b7 --- /dev/null +++ b/quantum/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 diff --git a/quantum/split_common/post_config.h b/quantum/split_common/post_config.h new file mode 100644 index 0000000000..0e59df3d06 --- /dev/null +++ b/quantum/split_common/post_config.h @@ -0,0 +1,15 @@ +#if defined(USE_I2C) || defined(EH) + // When using I2C, using rgblight implicitly involves split support. + #if defined(RGBLIGHT_ENABLE) && !defined(RGBLIGHT_SPLIT) + #define RGBLIGHT_SPLIT + #endif + +#else // use serial + // When using serial, the user must define RGBLIGHT_SPLIT explicitly + // in config.h as needed. + // see quantum/rgblight_post_config.h + #if defined(RGBLIGHT_ENABLE) && defined(RGBLIGHT_SPLIT) + // When using serial and RGBLIGHT_SPLIT need separate transaction + #define SERIAL_USE_MULTI_TRANSACTION + #endif +#endif diff --git a/quantum/split_common/transport.c b/quantum/split_common/transport.c index ab055ee656..7ea1a9cec9 100644 --- a/quantum/split_common/transport.c +++ b/quantum/split_common/transport.c @@ -25,36 +25,23 @@ extern backlight_config_t backlight_config; # include "i2c_master.h" # include "i2c_slave.h" -typedef struct __attribute__ ((__packed__)) { -#ifdef BACKLIGHT_ENABLE - uint8_t backlight_level; -#endif -#ifdef RGBLIGHT_ENABLE - uint32_t rgb_settings; +typedef struct _I2C_slave_buffer_t { + matrix_row_t smatrix[ROWS_PER_HAND]; + uint8_t backlight_level; +#if defined(RGBLIGHT_ENABLE) && defined(RGBLIGHT_SPLIT) + rgblight_syncinfo_t rgblight_sync; #endif #ifdef ENCODER_ENABLE - uint8_t encoder_state[NUMBER_OF_ENCODERS]; -#endif - // Keep matrix last, we are only using this for it's offset - uint8_t matrix_start[0]; -} transport_values_t; - -__attribute__ ((unused)) -static transport_values_t transport_values; - -#ifdef BACKLIGHT_ENABLE -# define I2C_BACKLIT_START (uint8_t)offsetof(transport_values_t, backlight_level) -#endif - -#ifdef RGBLIGHT_ENABLE -# define I2C_RGB_START (uint8_t)offsetof(transport_values_t, rgb_settings) + uint8_t encoder_state[NUMBER_OF_ENCODERS]; #endif +} I2C_slave_buffer_t; -#ifdef ENCODER_ENABLE -# define I2C_ENCODER_START (uint8_t)offsetof(transport_values_t, encoder_state) -#endif +static I2C_slave_buffer_t * const i2c_buffer = (I2C_slave_buffer_t *)i2c_slave_reg; -#define I2C_KEYMAP_START (uint8_t)offsetof(transport_values_t, matrix_start) +# define I2C_BACKLIGHT_START offsetof(I2C_slave_buffer_t, backlight_level) +# define I2C_RGB_START offsetof(I2C_slave_buffer_t, rgblight_sync) +# define I2C_KEYMAP_START offsetof(I2C_slave_buffer_t, smatrix) +# define I2C_ENCODER_START offsetof(I2C_slave_buffer_t, encoder_state) # define TIMEOUT 100 @@ -64,30 +51,32 @@ static transport_values_t transport_values; // Get rows from other half over i2c bool transport_master(matrix_row_t matrix[]) { - i2c_readReg(SLAVE_I2C_ADDRESS, I2C_KEYMAP_START, (void *)matrix, ROWS_PER_HAND * sizeof(matrix_row_t), TIMEOUT); + i2c_readReg(SLAVE_I2C_ADDRESS, I2C_KEYMAP_START, (void *)matrix, sizeof(i2c_buffer->smatrix), TIMEOUT); // write backlight info # ifdef BACKLIGHT_ENABLE uint8_t level = get_backlight_level(); - if (level != transport_values.backlight_level) { - if (i2c_writeReg(SLAVE_I2C_ADDRESS, I2C_BACKLIT_START, (void *)&level, sizeof(level), TIMEOUT) >= 0) { - transport_values.backlight_level = level; + if (level != i2c_buffer->backlight_level) { + if (i2c_writeReg(SLAVE_I2C_ADDRESS, I2C_BACKLIGHT_START, (void *)&level, sizeof(level), TIMEOUT) >= 0) { + i2c_buffer->backlight_level = level; } } # endif -# ifdef RGBLIGHT_ENABLE - uint32_t rgb = rgblight_read_dword(); - if (rgb != transport_values.rgb_settings) { - if (i2c_writeReg(SLAVE_I2C_ADDRESS, I2C_RGB_START, (void *)&rgb, sizeof(rgb), TIMEOUT) >= 0) { - transport_values.rgb_settings = rgb; +# if defined(RGBLIGHT_ENABLE) && defined(RGBLIGHT_SPLIT) + if (rgblight_get_change_flags()) { + rgblight_syncinfo_t rgblight_sync; + rgblight_get_syncinfo(&rgblight_sync); + if (i2c_writeReg(SLAVE_I2C_ADDRESS, I2C_RGB_START, + (void *)&rgblight_sync, sizeof(rgblight_sync), TIMEOUT) >= 0) { + rgblight_clear_change_flags(); } } # endif # ifdef ENCODER_ENABLE - i2c_readReg(SLAVE_I2C_ADDRESS, I2C_ENCODER_START, (void *)transport_values.encoder_state, sizeof(transport_values.encoder_state), TIMEOUT); - encoder_update_raw(&transport_values.encoder_state[0]); + i2c_readReg(SLAVE_I2C_ADDRESS, I2C_ENCODER_START, (void *)i2c_buffer->encoder_state, sizeof(I2C_slave_buffer_t.encoder_state), TIMEOUT); + encoder_update_raw(i2c_buffer->encoder_state); # endif return true; @@ -95,21 +84,23 @@ bool transport_master(matrix_row_t matrix[]) { void transport_slave(matrix_row_t matrix[]) { // Copy matrix to I2C buffer - memcpy((void*)(i2c_slave_reg + I2C_KEYMAP_START), (void *)matrix, ROWS_PER_HAND * sizeof(matrix_row_t) ); + memcpy((void*)i2c_buffer->smatrix, (void *)matrix, sizeof(i2c_buffer->smatrix)); // Read Backlight Info # ifdef BACKLIGHT_ENABLE - backlight_set(i2c_slave_reg[I2C_BACKLIT_START]); + backlight_set(i2c_buffer->backlight_level); # endif -# ifdef RGBLIGHT_ENABLE - uint32_t rgb = *(uint32_t *)(i2c_slave_reg + I2C_RGB_START); +# if defined(RGBLIGHT_ENABLE) && defined(RGBLIGHT_SPLIT) // Update the RGB with the new data - rgblight_update_dword(rgb); + if (i2c_buffer->rgblight_sync.status.change_flags != 0) { + rgblight_update_sync(&i2c_buffer->rgblight_sync, false); + i2c_buffer->rgblight_sync.status.change_flags = 0; + } # endif # ifdef ENCODER_ENABLE - encoder_state_raw((uint8_t*)(i2c_slave_reg + I2C_ENCODER_START)); + encoder_state_raw(i2c_buffer->encoder_state); # endif } @@ -121,53 +112,109 @@ void transport_slave_init(void) { i2c_slave_init(SLAVE_I2C_ADDRESS); } # include "serial.h" -typedef struct __attribute__ ((__packed__)) { +typedef struct _Serial_s2m_buffer_t { + // TODO: if MATRIX_COLS > 8 change to uint8_t packed_matrix[] for pack/unpack + matrix_row_t smatrix[ROWS_PER_HAND]; + # ifdef ENCODER_ENABLE uint8_t encoder_state[NUMBER_OF_ENCODERS]; # endif - // TODO: if MATRIX_COLS > 8 change to uint8_t packed_matrix[] for pack/unpack - matrix_row_t smatrix[ROWS_PER_HAND]; + } Serial_s2m_buffer_t; -typedef struct __attribute__ ((__packed__)) { +typedef struct _Serial_m2s_buffer_t { # ifdef BACKLIGHT_ENABLE uint8_t backlight_level; # endif -# if defined(RGBLIGHT_ENABLE) && defined(RGBLED_SPLIT) - rgblight_config_t rgblight_config; // not yet use - // - // When MCUs on both sides drive their respective RGB LED chains, - // it is necessary to synchronize, so it is necessary to communicate RGB - // information. In that case, define RGBLED_SPLIT with info on the number - // of LEDs on each half. - // - // Otherwise, if the master side MCU drives both sides RGB LED chains, - // there is no need to communicate. -# endif } Serial_m2s_buffer_t; +#if defined(RGBLIGHT_ENABLE) && defined(RGBLIGHT_SPLIT) +// When MCUs on both sides drive their respective RGB LED chains, +// it is necessary to synchronize, so it is necessary to communicate RGB +// information. In that case, define RGBLIGHT_SPLIT with info on the number +// of LEDs on each half. +// +// Otherwise, if the master side MCU drives both sides RGB LED chains, +// there is no need to communicate. + +typedef struct _Serial_rgblight_t { + rgblight_syncinfo_t rgblight_sync; +} Serial_rgblight_t; + +volatile Serial_rgblight_t serial_rgblight = {}; +uint8_t volatile status_rgblight = 0; +#endif + volatile Serial_s2m_buffer_t serial_s2m_buffer = {}; volatile Serial_m2s_buffer_t serial_m2s_buffer = {}; uint8_t volatile status0 = 0; +enum serial_transaction_id { + GET_SLAVE_MATRIX = 0, +#if defined(RGBLIGHT_ENABLE) && defined(RGBLIGHT_SPLIT) + PUT_RGBLIGHT, +#endif +}; + SSTD_t transactions[] = { - { + [GET_SLAVE_MATRIX] = { (uint8_t *)&status0, sizeof(serial_m2s_buffer), (uint8_t *)&serial_m2s_buffer, sizeof(serial_s2m_buffer), (uint8_t *)&serial_s2m_buffer, }, +#if defined(RGBLIGHT_ENABLE) && defined(RGBLIGHT_SPLIT) + [PUT_RGBLIGHT] = { + (uint8_t *)&status_rgblight, + sizeof(serial_rgblight), + (uint8_t *)&serial_rgblight, + 0, NULL // no slave to master transfer + }, +#endif }; void transport_master_init(void) { soft_serial_initiator_init(transactions, TID_LIMIT(transactions)); } void transport_slave_init(void) { soft_serial_target_init(transactions, TID_LIMIT(transactions)); } +#if defined(RGBLIGHT_ENABLE) && defined(RGBLIGHT_SPLIT) + +// rgblight synchronization information communication. + +void transport_rgblight_master(void) { + if (rgblight_get_change_flags()) { + rgblight_get_syncinfo((rgblight_syncinfo_t *)&serial_rgblight.rgblight_sync); + if (soft_serial_transaction(PUT_RGBLIGHT) == TRANSACTION_END) { + rgblight_clear_change_flags(); + } + } +} + +void transport_rgblight_slave(void) { + if (status_rgblight == TRANSACTION_ACCEPTED) { + rgblight_update_sync((rgblight_syncinfo_t *)&serial_rgblight.rgblight_sync, + false); + status_rgblight = TRANSACTION_END; + } +} + +#else +#define transport_rgblight_master() +#define transport_rgblight_slave() +#endif + bool transport_master(matrix_row_t matrix[]) { - if (soft_serial_transaction()) { +#ifndef SERIAL_USE_MULTI_TRANSACTION + if (soft_serial_transaction() != TRANSACTION_END) { return false; } +#else + transport_rgblight_master(); + if (soft_serial_transaction(GET_SLAVE_MATRIX) != TRANSACTION_END) { + return false; + } +#endif // TODO: if MATRIX_COLS > 8 change to unpack() for (int i = 0; i < ROWS_PER_HAND; ++i) { @@ -179,23 +226,15 @@ bool transport_master(matrix_row_t matrix[]) { serial_m2s_buffer.backlight_level = backlight_config.enable ? backlight_config.level : 0; # endif -# if defined(RGBLIGHT_ENABLE) && defined(RGBLED_SPLIT) - static rgblight_config_t prev_rgb = {~0}; - uint32_t rgb = rgblight_read_dword(); - if (rgb != prev_rgb.raw) { - serial_m2s_buffer.rgblight_config.raw = rgb; - prev_rgb.raw = rgb; - } -# endif - # ifdef ENCODER_ENABLE - encoder_update_raw((uint8_t*)&serial_s2m_buffer.encoder_state); + encoder_update_raw((uint8_t *)serial_s2m_buffer.encoder_state); # endif return true; } void transport_slave(matrix_row_t matrix[]) { + transport_rgblight_slave(); // TODO: if MATRIX_COLS > 8 change to pack() for (int i = 0; i < ROWS_PER_HAND; ++i) { serial_s2m_buffer.smatrix[i] = matrix[i]; @@ -203,14 +242,11 @@ void transport_slave(matrix_row_t matrix[]) { # ifdef BACKLIGHT_ENABLE backlight_set(serial_m2s_buffer.backlight_level); # endif -# if defined(RGBLIGHT_ENABLE) && defined(RGBLED_SPLIT) - // Update RGB config with the new data - rgblight_update_dword(serial_m2s_buffer.rgblight_config.raw); -# endif # ifdef ENCODER_ENABLE - encoder_state_raw((uint8_t*)&serial_s2m_buffer.encoder_state); + encoder_state_raw((uint8_t *)serial_s2m_buffer.encoder_state); # endif + } #endif |