diff options
Diffstat (limited to 'quantum/rgblight.c')
| -rw-r--r-- | quantum/rgblight.c | 100 |
1 files changed, 57 insertions, 43 deletions
diff --git a/quantum/rgblight.c b/quantum/rgblight.c index ac4ff9bfd..7d7d015ba 100644 --- a/quantum/rgblight.c +++ b/quantum/rgblight.c | |||
| @@ -29,7 +29,7 @@ | |||
| 29 | #endif | 29 | #endif |
| 30 | #include "wait.h" | 30 | #include "wait.h" |
| 31 | #include "progmem.h" | 31 | #include "progmem.h" |
| 32 | #include "timer.h" | 32 | #include "sync_timer.h" |
| 33 | #include "rgblight.h" | 33 | #include "rgblight.h" |
| 34 | #include "color.h" | 34 | #include "color.h" |
| 35 | #include "debug.h" | 35 | #include "debug.h" |
| @@ -42,6 +42,9 @@ | |||
| 42 | #ifndef MIN | 42 | #ifndef MIN |
| 43 | # define MIN(a, b) (((a) < (b)) ? (a) : (b)) | 43 | # define MIN(a, b) (((a) < (b)) ? (a) : (b)) |
| 44 | #endif | 44 | #endif |
| 45 | #ifndef MAX | ||
| 46 | # define MAX(a, b) (((a) > (b)) ? (a) : (b)) | ||
| 47 | #endif | ||
| 45 | 48 | ||
| 46 | #ifdef RGBLIGHT_SPLIT | 49 | #ifdef RGBLIGHT_SPLIT |
| 47 | /* for split keyboard */ | 50 | /* for split keyboard */ |
| @@ -700,18 +703,16 @@ static void rgblight_layers_write(void) { | |||
| 700 | 703 | ||
| 701 | # ifdef RGBLIGHT_LAYER_BLINK | 704 | # ifdef RGBLIGHT_LAYER_BLINK |
| 702 | rgblight_layer_mask_t _blinked_layer_mask = 0; | 705 | rgblight_layer_mask_t _blinked_layer_mask = 0; |
| 703 | uint16_t _blink_duration = 0; | ||
| 704 | static uint16_t _blink_timer; | 706 | static uint16_t _blink_timer; |
| 705 | 707 | ||
| 706 | void rgblight_blink_layer(uint8_t layer, uint16_t duration_ms) { | 708 | void rgblight_blink_layer(uint8_t layer, uint16_t duration_ms) { |
| 707 | rgblight_set_layer_state(layer, true); | 709 | rgblight_set_layer_state(layer, true); |
| 708 | _blinked_layer_mask |= (rgblight_layer_mask_t)1 << layer; | 710 | _blinked_layer_mask |= (rgblight_layer_mask_t)1 << layer; |
| 709 | _blink_timer = timer_read(); | 711 | _blink_timer = sync_timer_read() + duration_ms; |
| 710 | _blink_duration = duration_ms; | ||
| 711 | } | 712 | } |
| 712 | 713 | ||
| 713 | void rgblight_unblink_layers(void) { | 714 | void rgblight_unblink_layers(void) { |
| 714 | if (_blinked_layer_mask != 0 && timer_elapsed(_blink_timer) > _blink_duration) { | 715 | if (_blinked_layer_mask != 0 && timer_expired(sync_timer_read(), _blink_timer)) { |
| 715 | for (uint8_t layer = 0; layer < RGBLIGHT_MAX_LAYERS; layer++) { | 716 | for (uint8_t layer = 0; layer < RGBLIGHT_MAX_LAYERS; layer++) { |
| 716 | if ((_blinked_layer_mask & (rgblight_layer_mask_t)1 << layer) != 0) { | 717 | if ((_blinked_layer_mask & (rgblight_layer_mask_t)1 << layer) != 0) { |
| 717 | rgblight_set_layer_state(layer, false); | 718 | rgblight_set_layer_state(layer, false); |
| @@ -886,7 +887,7 @@ void rgblight_timer_enable(void) { | |||
| 886 | if (!is_static_effect(rgblight_config.mode)) { | 887 | if (!is_static_effect(rgblight_config.mode)) { |
| 887 | rgblight_status.timer_enabled = true; | 888 | rgblight_status.timer_enabled = true; |
| 888 | } | 889 | } |
| 889 | animation_status.last_timer = timer_read(); | 890 | animation_status.last_timer = sync_timer_read(); |
| 890 | RGBLIGHT_SPLIT_SET_CHANGE_TIMER_ENABLE; | 891 | RGBLIGHT_SPLIT_SET_CHANGE_TIMER_ENABLE; |
| 891 | dprintf("rgblight timer enabled.\n"); | 892 | dprintf("rgblight timer enabled.\n"); |
| 892 | } | 893 | } |
| @@ -989,24 +990,25 @@ void rgblight_task(void) { | |||
| 989 | # endif | 990 | # endif |
| 990 | # ifdef RGBLIGHT_EFFECT_TWINKLE | 991 | # ifdef RGBLIGHT_EFFECT_TWINKLE |
| 991 | else if (rgblight_status.base_mode == RGBLIGHT_MODE_TWINKLE) { | 992 | else if (rgblight_status.base_mode == RGBLIGHT_MODE_TWINKLE) { |
| 992 | interval_time = get_interval_time(&RGBLED_TWINKLE_INTERVALS[delta % 3], 5, 50); | 993 | interval_time = get_interval_time(&RGBLED_TWINKLE_INTERVALS[delta % 3], 5, 30); |
| 993 | effect_func = (effect_func_t)rgblight_effect_twinkle; | 994 | effect_func = (effect_func_t)rgblight_effect_twinkle; |
| 994 | } | 995 | } |
| 995 | # endif | 996 | # endif |
| 996 | if (animation_status.restart) { | 997 | if (animation_status.restart) { |
| 997 | animation_status.restart = false; | 998 | animation_status.restart = false; |
| 998 | animation_status.last_timer = timer_read() - interval_time - 1; | 999 | animation_status.last_timer = sync_timer_read(); |
| 999 | animation_status.pos16 = 0; // restart signal to local each effect | 1000 | animation_status.pos16 = 0; // restart signal to local each effect |
| 1000 | } | 1001 | } |
| 1001 | if (timer_elapsed(animation_status.last_timer) >= interval_time) { | 1002 | uint16_t now = sync_timer_read(); |
| 1003 | if (timer_expired(now, animation_status.last_timer)) { | ||
| 1002 | # if defined(RGBLIGHT_SPLIT) && !defined(RGBLIGHT_SPLIT_NO_ANIMATION_SYNC) | 1004 | # if defined(RGBLIGHT_SPLIT) && !defined(RGBLIGHT_SPLIT_NO_ANIMATION_SYNC) |
| 1003 | static uint16_t report_last_timer = 0; | 1005 | static uint16_t report_last_timer = 0; |
| 1004 | static bool tick_flag = false; | 1006 | static bool tick_flag = false; |
| 1005 | uint16_t oldpos16; | 1007 | uint16_t oldpos16; |
| 1006 | if (tick_flag) { | 1008 | if (tick_flag) { |
| 1007 | tick_flag = false; | 1009 | tick_flag = false; |
| 1008 | if (timer_elapsed(report_last_timer) >= 30000) { | 1010 | if (timer_expired(now, report_last_timer)) { |
| 1009 | report_last_timer = timer_read(); | 1011 | report_last_timer += 30000; |
| 1010 | dprintf("rgblight animation tick report to slave\n"); | 1012 | dprintf("rgblight animation tick report to slave\n"); |
| 1011 | RGBLIGHT_SPLIT_ANIMATION_TICK; | 1013 | RGBLIGHT_SPLIT_ANIMATION_TICK; |
| 1012 | } | 1014 | } |
| @@ -1030,8 +1032,7 @@ void rgblight_task(void) { | |||
| 1030 | 1032 | ||
| 1031 | #endif /* RGBLIGHT_USE_TIMER */ | 1033 | #endif /* RGBLIGHT_USE_TIMER */ |
| 1032 | 1034 | ||
| 1033 | // Effects | 1035 | #if defined(RGBLIGHT_EFFECT_BREATHING) || defined(RGBLIGHT_EFFECT_TWINKLE) |
| 1034 | #ifdef RGBLIGHT_EFFECT_BREATHING | ||
| 1035 | 1036 | ||
| 1036 | # ifndef RGBLIGHT_EFFECT_BREATHE_CENTER | 1037 | # ifndef RGBLIGHT_EFFECT_BREATHE_CENTER |
| 1037 | # ifndef RGBLIGHT_BREATHE_TABLE_SIZE | 1038 | # ifndef RGBLIGHT_BREATHE_TABLE_SIZE |
| @@ -1040,17 +1041,24 @@ void rgblight_task(void) { | |||
| 1040 | # include <rgblight_breathe_table.h> | 1041 | # include <rgblight_breathe_table.h> |
| 1041 | # endif | 1042 | # endif |
| 1042 | 1043 | ||
| 1043 | __attribute__((weak)) const uint8_t RGBLED_BREATHING_INTERVALS[] PROGMEM = {30, 20, 10, 5}; | 1044 | static uint8_t breathe_calc(uint8_t pos) { |
| 1044 | |||
| 1045 | void rgblight_effect_breathing(animation_status_t *anim) { | ||
| 1046 | float val; | ||
| 1047 | |||
| 1048 | // http://sean.voisen.org/blog/2011/10/breathing-led-with-arduino/ | 1045 | // http://sean.voisen.org/blog/2011/10/breathing-led-with-arduino/ |
| 1049 | # ifdef RGBLIGHT_EFFECT_BREATHE_TABLE | 1046 | # ifdef RGBLIGHT_EFFECT_BREATHE_TABLE |
| 1050 | val = pgm_read_byte(&rgblight_effect_breathe_table[anim->pos / table_scale]); | 1047 | return pgm_read_byte(&rgblight_effect_breathe_table[pos / table_scale]); |
| 1051 | # else | 1048 | # else |
| 1052 | val = (exp(sin((anim->pos / 255.0) * M_PI)) - RGBLIGHT_EFFECT_BREATHE_CENTER / M_E) * (RGBLIGHT_EFFECT_BREATHE_MAX / (M_E - 1 / M_E)); | 1049 | return (exp(sin((pos / 255.0) * M_PI)) - RGBLIGHT_EFFECT_BREATHE_CENTER / M_E) * (RGBLIGHT_EFFECT_BREATHE_MAX / (M_E - 1 / M_E)); |
| 1053 | # endif | 1050 | # endif |
| 1051 | } | ||
| 1052 | |||
| 1053 | #endif | ||
| 1054 | |||
| 1055 | // Effects | ||
| 1056 | #ifdef RGBLIGHT_EFFECT_BREATHING | ||
| 1057 | |||
| 1058 | __attribute__((weak)) const uint8_t RGBLED_BREATHING_INTERVALS[] PROGMEM = {30, 20, 10, 5}; | ||
| 1059 | |||
| 1060 | void rgblight_effect_breathing(animation_status_t *anim) { | ||
| 1061 | uint8_t val = breathe_calc(anim->pos); | ||
| 1054 | rgblight_sethsv_noeeprom_old(rgblight_config.hue, rgblight_config.sat, val); | 1062 | rgblight_sethsv_noeeprom_old(rgblight_config.hue, rgblight_config.sat, val); |
| 1055 | anim->pos = (anim->pos + 1); | 1063 | anim->pos = (anim->pos + 1); |
| 1056 | } | 1064 | } |
| @@ -1302,48 +1310,54 @@ void rgblight_effect_alternating(animation_status_t *anim) { | |||
| 1302 | #endif | 1310 | #endif |
| 1303 | 1311 | ||
| 1304 | #ifdef RGBLIGHT_EFFECT_TWINKLE | 1312 | #ifdef RGBLIGHT_EFFECT_TWINKLE |
| 1305 | __attribute__((weak)) const uint8_t RGBLED_TWINKLE_INTERVALS[] PROGMEM = {50, 25, 10}; | 1313 | __attribute__((weak)) const uint8_t RGBLED_TWINKLE_INTERVALS[] PROGMEM = {30, 15, 5}; |
| 1306 | 1314 | ||
| 1307 | typedef struct PACKED { | 1315 | typedef struct PACKED { |
| 1308 | HSV hsv; | 1316 | HSV hsv; |
| 1309 | uint8_t life; | 1317 | uint8_t life; |
| 1310 | bool up; | 1318 | uint8_t max_life; |
| 1311 | } TwinkleState; | 1319 | } TwinkleState; |
| 1312 | 1320 | ||
| 1313 | static TwinkleState led_twinkle_state[RGBLED_NUM]; | 1321 | static TwinkleState led_twinkle_state[RGBLED_NUM]; |
| 1314 | 1322 | ||
| 1315 | void rgblight_effect_twinkle(animation_status_t *anim) { | 1323 | void rgblight_effect_twinkle(animation_status_t *anim) { |
| 1316 | bool random_color = anim->delta / 3; | 1324 | const bool random_color = anim->delta / 3; |
| 1317 | bool restart = anim->pos == 0; | 1325 | const bool restart = anim->pos == 0; |
| 1318 | anim->pos = 1; | 1326 | anim->pos = 1; |
| 1327 | |||
| 1328 | const uint8_t bottom = breathe_calc(0); | ||
| 1329 | const uint8_t top = breathe_calc(127); | ||
| 1330 | |||
| 1331 | uint8_t frac(uint8_t n, uint8_t d) { return (uint16_t)255 * n / d; } | ||
| 1332 | uint8_t scale(uint16_t v, uint8_t scale) { return (v * scale) >> 8; } | ||
| 1319 | 1333 | ||
| 1320 | for (uint8_t i = 0; i < rgblight_ranges.effect_num_leds; i++) { | 1334 | for (uint8_t i = 0; i < rgblight_ranges.effect_num_leds; i++) { |
| 1321 | TwinkleState *t = &(led_twinkle_state[i]); | 1335 | TwinkleState *t = &(led_twinkle_state[i]); |
| 1322 | HSV * c = &(t->hsv); | 1336 | HSV * c = &(t->hsv); |
| 1337 | |||
| 1338 | if (!random_color) { | ||
| 1339 | c->h = rgblight_config.hue; | ||
| 1340 | c->s = rgblight_config.sat; | ||
| 1341 | } | ||
| 1342 | |||
| 1323 | if (restart) { | 1343 | if (restart) { |
| 1324 | // Restart | 1344 | // Restart |
| 1325 | t->life = 0; | 1345 | t->life = 0; |
| 1326 | t->hsv.v = 0; | 1346 | c->v = 0; |
| 1327 | } else if (t->life) { | 1347 | } else if (t->life) { |
| 1328 | // This LED is already on, either brightening or dimming | 1348 | // This LED is already on, either brightening or dimming |
| 1329 | t->life--; | 1349 | t->life--; |
| 1330 | uint8_t on = t->up ? RGBLIGHT_EFFECT_TWINKLE_LIFE - t->life : t->life; | 1350 | uint8_t unscaled = frac(breathe_calc(frac(t->life, t->max_life)) - bottom, top - bottom); |
| 1331 | c->v = (uint16_t)rgblight_config.val * on / RGBLIGHT_EFFECT_TWINKLE_LIFE; | 1351 | c->v = scale(rgblight_config.val, unscaled); |
| 1332 | if (t->life == 0 && t->up) { | 1352 | } else if (rand() < scale((uint16_t)RAND_MAX * RGBLIGHT_EFFECT_TWINKLE_PROBABILITY, 127 + rgblight_config.val / 2)) { |
| 1333 | t->up = false; | ||
| 1334 | t->life = RGBLIGHT_EFFECT_TWINKLE_LIFE; | ||
| 1335 | } | ||
| 1336 | if (!random_color) { | ||
| 1337 | c->h = rgblight_config.hue; | ||
| 1338 | c->s = rgblight_config.sat; | ||
| 1339 | } | ||
| 1340 | } else if (rand() < RAND_MAX * RGBLIGHT_EFFECT_TWINKLE_PROBABILITY) { | ||
| 1341 | // This LED is off, but was randomly selected to start brightening | 1353 | // This LED is off, but was randomly selected to start brightening |
| 1342 | c->h = random_color ? rand() % 0xFF : rgblight_config.hue; | 1354 | if (random_color) { |
| 1343 | c->s = random_color ? (rand() % (rgblight_config.sat / 2)) + (rgblight_config.sat / 2) : rgblight_config.sat; | 1355 | c->h = rand() % 0xFF; |
| 1344 | c->v = 0; | 1356 | c->s = (rand() % (rgblight_config.sat / 2)) + (rgblight_config.sat / 2); |
| 1345 | t->life = RGBLIGHT_EFFECT_TWINKLE_LIFE; | 1357 | } |
| 1346 | t->up = true; | 1358 | c->v = 0; |
| 1359 | t->max_life = MAX(20, MIN(RGBLIGHT_EFFECT_TWINKLE_LIFE, rgblight_config.val)); | ||
| 1360 | t->life = t->max_life; | ||
| 1347 | } else { | 1361 | } else { |
| 1348 | // This LED is off, and was NOT selected to start brightening | 1362 | // This LED is off, and was NOT selected to start brightening |
| 1349 | } | 1363 | } |
