diff options
Diffstat (limited to 'quantum/rgblight.c')
| -rw-r--r-- | quantum/rgblight.c | 102 |
1 files changed, 58 insertions, 44 deletions
diff --git a/quantum/rgblight.c b/quantum/rgblight.c index beeef6568..59b3f4026 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 */ |
| @@ -684,18 +687,16 @@ static void rgblight_layers_write(void) { | |||
| 684 | 687 | ||
| 685 | # ifdef RGBLIGHT_LAYER_BLINK | 688 | # ifdef RGBLIGHT_LAYER_BLINK |
| 686 | rgblight_layer_mask_t _blinked_layer_mask = 0; | 689 | rgblight_layer_mask_t _blinked_layer_mask = 0; |
| 687 | uint16_t _blink_duration = 0; | ||
| 688 | static uint16_t _blink_timer; | 690 | static uint16_t _blink_timer; |
| 689 | 691 | ||
| 690 | void rgblight_blink_layer(uint8_t layer, uint16_t duration_ms) { | 692 | void rgblight_blink_layer(uint8_t layer, uint16_t duration_ms) { |
| 691 | rgblight_set_layer_state(layer, true); | 693 | rgblight_set_layer_state(layer, true); |
| 692 | _blinked_layer_mask |= (rgblight_layer_mask_t)1 << layer; | 694 | _blinked_layer_mask |= (rgblight_layer_mask_t)1 << layer; |
| 693 | _blink_timer = timer_read(); | 695 | _blink_timer = sync_timer_read() + duration_ms; |
| 694 | _blink_duration = duration_ms; | ||
| 695 | } | 696 | } |
| 696 | 697 | ||
| 697 | void rgblight_unblink_layers(void) { | 698 | void rgblight_unblink_layers(void) { |
| 698 | if (_blinked_layer_mask != 0 && timer_elapsed(_blink_timer) > _blink_duration) { | 699 | if (_blinked_layer_mask != 0 && timer_expired(sync_timer_read(), _blink_timer)) { |
| 699 | for (uint8_t layer = 0; layer < RGBLIGHT_MAX_LAYERS; layer++) { | 700 | for (uint8_t layer = 0; layer < RGBLIGHT_MAX_LAYERS; layer++) { |
| 700 | if ((_blinked_layer_mask & (rgblight_layer_mask_t)1 << layer) != 0) { | 701 | if ((_blinked_layer_mask & (rgblight_layer_mask_t)1 << layer) != 0) { |
| 701 | rgblight_set_layer_state(layer, false); | 702 | rgblight_set_layer_state(layer, false); |
| @@ -799,7 +800,7 @@ void rgblight_update_sync(rgblight_syncinfo_t *syncinfo, bool write_to_eeprom) { | |||
| 799 | animation_status.restart = true; | 800 | animation_status.restart = true; |
| 800 | } | 801 | } |
| 801 | # endif /* RGBLIGHT_SPLIT_NO_ANIMATION_SYNC */ | 802 | # endif /* RGBLIGHT_SPLIT_NO_ANIMATION_SYNC */ |
| 802 | # endif /* RGBLIGHT_USE_TIMER */ | 803 | # endif /* RGBLIGHT_USE_TIMER */ |
| 803 | } | 804 | } |
| 804 | #endif /* RGBLIGHT_SPLIT */ | 805 | #endif /* RGBLIGHT_SPLIT */ |
| 805 | 806 | ||
| @@ -832,7 +833,7 @@ void rgblight_timer_enable(void) { | |||
| 832 | if (!is_static_effect(rgblight_config.mode)) { | 833 | if (!is_static_effect(rgblight_config.mode)) { |
| 833 | rgblight_status.timer_enabled = true; | 834 | rgblight_status.timer_enabled = true; |
| 834 | } | 835 | } |
| 835 | animation_status.last_timer = timer_read(); | 836 | animation_status.last_timer = sync_timer_read(); |
| 836 | RGBLIGHT_SPLIT_SET_CHANGE_TIMER_ENABLE; | 837 | RGBLIGHT_SPLIT_SET_CHANGE_TIMER_ENABLE; |
| 837 | dprintf("rgblight timer enabled.\n"); | 838 | dprintf("rgblight timer enabled.\n"); |
| 838 | } | 839 | } |
| @@ -935,24 +936,25 @@ void rgblight_task(void) { | |||
| 935 | # endif | 936 | # endif |
| 936 | # ifdef RGBLIGHT_EFFECT_TWINKLE | 937 | # ifdef RGBLIGHT_EFFECT_TWINKLE |
| 937 | else if (rgblight_status.base_mode == RGBLIGHT_MODE_TWINKLE) { | 938 | else if (rgblight_status.base_mode == RGBLIGHT_MODE_TWINKLE) { |
| 938 | interval_time = get_interval_time(&RGBLED_TWINKLE_INTERVALS[delta % 3], 5, 50); | 939 | interval_time = get_interval_time(&RGBLED_TWINKLE_INTERVALS[delta % 3], 5, 30); |
| 939 | effect_func = (effect_func_t)rgblight_effect_twinkle; | 940 | effect_func = (effect_func_t)rgblight_effect_twinkle; |
| 940 | } | 941 | } |
| 941 | # endif | 942 | # endif |
| 942 | if (animation_status.restart) { | 943 | if (animation_status.restart) { |
| 943 | animation_status.restart = false; | 944 | animation_status.restart = false; |
| 944 | animation_status.last_timer = timer_read() - interval_time - 1; | 945 | animation_status.last_timer = sync_timer_read(); |
| 945 | animation_status.pos16 = 0; // restart signal to local each effect | 946 | animation_status.pos16 = 0; // restart signal to local each effect |
| 946 | } | 947 | } |
| 947 | if (timer_elapsed(animation_status.last_timer) >= interval_time) { | 948 | uint16_t now = sync_timer_read(); |
| 949 | if (timer_expired(now, animation_status.last_timer)) { | ||
| 948 | # if defined(RGBLIGHT_SPLIT) && !defined(RGBLIGHT_SPLIT_NO_ANIMATION_SYNC) | 950 | # if defined(RGBLIGHT_SPLIT) && !defined(RGBLIGHT_SPLIT_NO_ANIMATION_SYNC) |
| 949 | static uint16_t report_last_timer = 0; | 951 | static uint16_t report_last_timer = 0; |
| 950 | static bool tick_flag = false; | 952 | static bool tick_flag = false; |
| 951 | uint16_t oldpos16; | 953 | uint16_t oldpos16; |
| 952 | if (tick_flag) { | 954 | if (tick_flag) { |
| 953 | tick_flag = false; | 955 | tick_flag = false; |
| 954 | if (timer_elapsed(report_last_timer) >= 30000) { | 956 | if (timer_expired(now, report_last_timer)) { |
| 955 | report_last_timer = timer_read(); | 957 | report_last_timer += 30000; |
| 956 | dprintf("rgblight animation tick report to slave\n"); | 958 | dprintf("rgblight animation tick report to slave\n"); |
| 957 | RGBLIGHT_SPLIT_ANIMATION_TICK; | 959 | RGBLIGHT_SPLIT_ANIMATION_TICK; |
| 958 | } | 960 | } |
| @@ -976,8 +978,7 @@ void rgblight_task(void) { | |||
| 976 | 978 | ||
| 977 | #endif /* RGBLIGHT_USE_TIMER */ | 979 | #endif /* RGBLIGHT_USE_TIMER */ |
| 978 | 980 | ||
| 979 | // Effects | 981 | #if defined(RGBLIGHT_EFFECT_BREATHING) || defined(RGBLIGHT_EFFECT_TWINKLE) |
| 980 | #ifdef RGBLIGHT_EFFECT_BREATHING | ||
| 981 | 982 | ||
| 982 | # ifndef RGBLIGHT_EFFECT_BREATHE_CENTER | 983 | # ifndef RGBLIGHT_EFFECT_BREATHE_CENTER |
| 983 | # ifndef RGBLIGHT_BREATHE_TABLE_SIZE | 984 | # ifndef RGBLIGHT_BREATHE_TABLE_SIZE |
| @@ -986,17 +987,24 @@ void rgblight_task(void) { | |||
| 986 | # include <rgblight_breathe_table.h> | 987 | # include <rgblight_breathe_table.h> |
| 987 | # endif | 988 | # endif |
| 988 | 989 | ||
| 989 | __attribute__((weak)) const uint8_t RGBLED_BREATHING_INTERVALS[] PROGMEM = {30, 20, 10, 5}; | 990 | static uint8_t breathe_calc(uint8_t pos) { |
| 990 | |||
| 991 | void rgblight_effect_breathing(animation_status_t *anim) { | ||
| 992 | float val; | ||
| 993 | |||
| 994 | // http://sean.voisen.org/blog/2011/10/breathing-led-with-arduino/ | 991 | // http://sean.voisen.org/blog/2011/10/breathing-led-with-arduino/ |
| 995 | # ifdef RGBLIGHT_EFFECT_BREATHE_TABLE | 992 | # ifdef RGBLIGHT_EFFECT_BREATHE_TABLE |
| 996 | val = pgm_read_byte(&rgblight_effect_breathe_table[anim->pos / table_scale]); | 993 | return pgm_read_byte(&rgblight_effect_breathe_table[pos / table_scale]); |
| 997 | # else | 994 | # else |
| 998 | val = (exp(sin((anim->pos / 255.0) * M_PI)) - RGBLIGHT_EFFECT_BREATHE_CENTER / M_E) * (RGBLIGHT_EFFECT_BREATHE_MAX / (M_E - 1 / M_E)); | 995 | return (exp(sin((pos / 255.0) * M_PI)) - RGBLIGHT_EFFECT_BREATHE_CENTER / M_E) * (RGBLIGHT_EFFECT_BREATHE_MAX / (M_E - 1 / M_E)); |
| 999 | # endif | 996 | # endif |
| 997 | } | ||
| 998 | |||
| 999 | #endif | ||
| 1000 | |||
| 1001 | // Effects | ||
| 1002 | #ifdef RGBLIGHT_EFFECT_BREATHING | ||
| 1003 | |||
| 1004 | __attribute__((weak)) const uint8_t RGBLED_BREATHING_INTERVALS[] PROGMEM = {30, 20, 10, 5}; | ||
| 1005 | |||
| 1006 | void rgblight_effect_breathing(animation_status_t *anim) { | ||
| 1007 | uint8_t val = breathe_calc(anim->pos); | ||
| 1000 | rgblight_sethsv_noeeprom_old(rgblight_config.hue, rgblight_config.sat, val); | 1008 | rgblight_sethsv_noeeprom_old(rgblight_config.hue, rgblight_config.sat, val); |
| 1001 | anim->pos = (anim->pos + 1); | 1009 | anim->pos = (anim->pos + 1); |
| 1002 | } | 1010 | } |
| @@ -1248,48 +1256,54 @@ void rgblight_effect_alternating(animation_status_t *anim) { | |||
| 1248 | #endif | 1256 | #endif |
| 1249 | 1257 | ||
| 1250 | #ifdef RGBLIGHT_EFFECT_TWINKLE | 1258 | #ifdef RGBLIGHT_EFFECT_TWINKLE |
| 1251 | __attribute__((weak)) const uint8_t RGBLED_TWINKLE_INTERVALS[] PROGMEM = {50, 25, 10}; | 1259 | __attribute__((weak)) const uint8_t RGBLED_TWINKLE_INTERVALS[] PROGMEM = {30, 15, 5}; |
| 1252 | 1260 | ||
| 1253 | typedef struct PACKED { | 1261 | typedef struct PACKED { |
| 1254 | HSV hsv; | 1262 | HSV hsv; |
| 1255 | uint8_t life; | 1263 | uint8_t life; |
| 1256 | bool up; | 1264 | uint8_t max_life; |
| 1257 | } TwinkleState; | 1265 | } TwinkleState; |
| 1258 | 1266 | ||
| 1259 | static TwinkleState led_twinkle_state[RGBLED_NUM]; | 1267 | static TwinkleState led_twinkle_state[RGBLED_NUM]; |
| 1260 | 1268 | ||
| 1261 | void rgblight_effect_twinkle(animation_status_t *anim) { | 1269 | void rgblight_effect_twinkle(animation_status_t *anim) { |
| 1262 | bool random_color = anim->delta / 3; | 1270 | const bool random_color = anim->delta / 3; |
| 1263 | bool restart = anim->pos == 0; | 1271 | const bool restart = anim->pos == 0; |
| 1264 | anim->pos = 1; | 1272 | anim->pos = 1; |
| 1273 | |||
| 1274 | const uint8_t bottom = breathe_calc(0); | ||
| 1275 | const uint8_t top = breathe_calc(127); | ||
| 1276 | |||
| 1277 | uint8_t frac(uint8_t n, uint8_t d) { return (uint16_t)255 * n / d; } | ||
| 1278 | uint8_t scale(uint16_t v, uint8_t scale) { return (v * scale) >> 8; } | ||
| 1265 | 1279 | ||
| 1266 | for (uint8_t i = 0; i < rgblight_ranges.effect_num_leds; i++) { | 1280 | for (uint8_t i = 0; i < rgblight_ranges.effect_num_leds; i++) { |
| 1267 | TwinkleState *t = &(led_twinkle_state[i]); | 1281 | TwinkleState *t = &(led_twinkle_state[i]); |
| 1268 | HSV * c = &(t->hsv); | 1282 | HSV * c = &(t->hsv); |
| 1283 | |||
| 1284 | if (!random_color) { | ||
| 1285 | c->h = rgblight_config.hue; | ||
| 1286 | c->s = rgblight_config.sat; | ||
| 1287 | } | ||
| 1288 | |||
| 1269 | if (restart) { | 1289 | if (restart) { |
| 1270 | // Restart | 1290 | // Restart |
| 1271 | t->life = 0; | 1291 | t->life = 0; |
| 1272 | t->hsv.v = 0; | 1292 | c->v = 0; |
| 1273 | } else if (t->life) { | 1293 | } else if (t->life) { |
| 1274 | // This LED is already on, either brightening or dimming | 1294 | // This LED is already on, either brightening or dimming |
| 1275 | t->life--; | 1295 | t->life--; |
| 1276 | uint8_t on = t->up ? RGBLIGHT_EFFECT_TWINKLE_LIFE - t->life : t->life; | 1296 | uint8_t unscaled = frac(breathe_calc(frac(t->life, t->max_life)) - bottom, top - bottom); |
| 1277 | c->v = (uint16_t)rgblight_config.val * on / RGBLIGHT_EFFECT_TWINKLE_LIFE; | 1297 | c->v = scale(rgblight_config.val, unscaled); |
| 1278 | if (t->life == 0 && t->up) { | 1298 | } else if (rand() < scale((uint16_t)RAND_MAX * RGBLIGHT_EFFECT_TWINKLE_PROBABILITY, 127 + rgblight_config.val / 2)) { |
| 1279 | t->up = false; | ||
| 1280 | t->life = RGBLIGHT_EFFECT_TWINKLE_LIFE; | ||
| 1281 | } | ||
| 1282 | if (!random_color) { | ||
| 1283 | c->h = rgblight_config.hue; | ||
| 1284 | c->s = rgblight_config.sat; | ||
| 1285 | } | ||
| 1286 | } else if (rand() < RAND_MAX * RGBLIGHT_EFFECT_TWINKLE_PROBABILITY) { | ||
| 1287 | // This LED is off, but was randomly selected to start brightening | 1299 | // This LED is off, but was randomly selected to start brightening |
| 1288 | c->h = random_color ? rand() % 0xFF : rgblight_config.hue; | 1300 | if (random_color) { |
| 1289 | c->s = random_color ? (rand() % (rgblight_config.sat / 2)) + (rgblight_config.sat / 2) : rgblight_config.sat; | 1301 | c->h = rand() % 0xFF; |
| 1290 | c->v = 0; | 1302 | c->s = (rand() % (rgblight_config.sat / 2)) + (rgblight_config.sat / 2); |
| 1291 | t->life = RGBLIGHT_EFFECT_TWINKLE_LIFE; | 1303 | } |
| 1292 | t->up = true; | 1304 | c->v = 0; |
| 1305 | t->max_life = MAX(20, MIN(RGBLIGHT_EFFECT_TWINKLE_LIFE, rgblight_config.val)); | ||
| 1306 | t->life = t->max_life; | ||
| 1293 | } else { | 1307 | } else { |
| 1294 | // This LED is off, and was NOT selected to start brightening | 1308 | // This LED is off, and was NOT selected to start brightening |
| 1295 | } | 1309 | } |
