/* * ledprog.c: led programs */ #include "matrix.h" #include "misc/tinymt.h" static uint32_t s[8] = {0}; static uint32_t t[8] = {0}; void lp_ribbon_init() { uint8_t i; for (i = 0; i < 8; i++) { s[i] = 0; } } void lp_ribbon_upward(uint16_t wait, uint16_t rate, uint8_t fade) { uint32_t i; uint32_t x; /* 0: state 1: timeout 2: index */ if (fade > 0x80) fade = 0x80; // reduce 1-frame bright blip for (i = 0; i < sizeof(led_set.ribbon); i++) { if (led_set.ribbon[i] >= 0xd0) { led_set.ribbon[i] = 0xd0; } } switch (s[0]) { case 0: { // timeout if (!s[1]) { s[0]++; s[2] = 0; return; } s[1]--; break; } case 1: { // upward trails // rate delay if (!s[1]) { s[1] = rate; } else { s[1]--; break; } x = s[2]++; // are we done? if (x >= sizeof(led_set.ribbon)) { s[0] = 0; s[1] = wait; break; } // fade in and up led_set.ribbon[x] = 0x20; if (x) led_set.ribbon[x - 1] = 0x66; if (x > 1) led_set.ribbon[x - 2] = 0xef; } } // fade out LEDs for (i = 0; i < sizeof(led_set.ribbon); i++) { if (led_set.ribbon[i] >= 0x70) { led_set.ribbon[i] -= fade; } if (led_set.ribbon[i] >= fade) { led_set.ribbon[i] -= fade; } else { // led_set.ribbon[i] >>= 1; if (led_set.ribbon[i]) led_set.ribbon[i]--; } } matrix_flag_update(); } void lp_ribbon_twinkle(uint8_t idle, uint8_t max, uint8_t thresh_lo, uint8_t thresh_hi) { /* idle: attempted idle target. ideally an odd number not a power of two. max: maximum brightness. anything higher is clamped to this thresh_lo: rand must be lower than this to make any adjustment this cycle thresh_hi: rand must be this or higher to force a bright twinkle */ uint32_t i; uint32_t w, x; s[1]++; for (i = 0; i < sizeof(led_set.ribbon); i++) { x = prng_get8(); if (x < thresh_lo) { w = (idle > 3) ? 3 : idle; // swing around idle level if (led_set.ribbon[i] > idle) { led_set.ribbon[i] >>= 1; } else { led_set.ribbon[i] += (w - 1); } } // only make bright stars every 4 frames if ((x >= thresh_hi) && ((s[1] & 3) == 0)) { w = prng_get8(); led_set.ribbon[i] += w; if (led_set.ribbon[i] > max) { led_set.ribbon[i] = max; } } } matrix_flag_update(); } void lp_aii_init() { uint8_t i; for (i = 0; i < 8; i++) { t[i] = 0; } // also clear LEDs for (int i = 0; i < sizeof(led_set.a); i++) { led_set.a[i] = 0; } for (int i = 0; i < sizeof(led_set.ii_lf); i++) { led_set.ii_lf[i] = 0; led_set.ii_rt[i] = 0; } matrix_flag_update(); } void lp_aii_filldown(uint16_t prewait, uint16_t downrate, uint16_t postwait, uint8_t setrate, uint8_t max) { /* 0: state 1: timeout 2: index or setrate >>= 1 */ uint32_t i; uint32_t x; if (setrate == 1) setrate = 2; switch (t[0]) { case 0: // timeout before start case 2: { // timeout after set if (!t[1]) { t[0]++; t[2] = 0; return; } t[1]--; break; } case 1: { // fill down // rate delay if (!t[1]) { t[1] = downrate; } else { t[1]--; break; } x = t[2]++; // done filling? if (x > 10) { t[0]++; t[1] = postwait; } for (i = 0; i <= x; i++) { led_set.a[9 + i] += setrate; if (led_set.a[9 + i] > max) led_set.a[9 + i] = max; led_set.a[9 - i] += setrate; if (led_set.a[9 - i] > max) led_set.a[9 - i] = max; } break; } case 3: { // fade out x = 0; t[2] = setrate >>= 1; for (i = 0; i < sizeof(led_set.a); i++) { if (led_set.a[i] < setrate) { led_set.a[i] = 0; } else { led_set.a[i] -= setrate; x++; } } // all blank? if (!x) { t[0] = 0; t[1] = prewait; } } } for (i = 0; i < 5; i++) { led_set.ii_lf[i] = led_set.ii_rt[i] = led_set.a[i + 12]; } matrix_flag_update(); } void lp_aii_bounce(uint8_t rate, uint8_t set, uint8_t faderate, uint8_t fadeamt) { /* 0: direction 1: rate timeout 2: faderate timeout 3: index 4: changedir timeout */ uint8_t *a; uint32_t i; uint32_t x; if (!t[1]) { if (t[4]) { t[4]--; if (t[4]) { goto fadeout; } } t[1] = rate; t[3]++; if (t[3] >= 19) { t[0] ^= 1; t[3] = 0; t[4] = rate << 2; } if (t[0]) { x = 18 - t[3]; } else { x = t[3]; } led_set.a[x] = set; if (t[3] >= 3) { if (t[3] <= 7) { led_set.ii_lf[7 - t[3]] = set >> 1; } } if (t[3] >= 13) { if (t[3] <= 17) { led_set.ii_rt[t[3] - 13] = set >> 1; } } } t[1]--; fadeout: if (!t[2]) { t[2] = faderate; a = (uint8_t *)&led_set.a; for (i = 0; i < (sizeof(led_set.a) + sizeof(led_set.ii_lf) + sizeof(led_set.ii_rt)); i++) { if (*a <= fadeamt) { *a = 0; } else { *a -= fadeamt; } a++; } } t[2]--; }