#include "pattern/twinkle.h" #include #include // The shape of a "spike" uint8_t w_arr[91] = {1, 2, 4, 7, 11, 17, 24, 33, 44, 56, 70, 85, 101, 117, 134, 151, 167, 183, 197, 210, 222, 232, 240, 247, 251, 254, 255, 255, 253, 250, 246, 240, 234, 227, 219, 211, 202, 194, 185, 176, 167, 158, 149, 140, 132, 123, 116, 108, 101, 94, 87, 81, 75, 69, 64, 59, 54, 50, 46, 42, 39, 35, 32, 30, 27, 25, 22, 20, 18, 17, 15, 14, 12, 11, 10, 9, 8, 7, 6, 6, 5, 4, 4, 3, 3, 3, 2, 2, 2, 1, 1}; static inline uint8_t byte_scale(uint8_t n, uint8_t sc) { return n * sc / 255; } static uint8_t calc_w(uint8_t n, uint8_t shift) { uint8_t s = byte_scale(shift, 164); uint8_t n_p = byte_scale(n, 255 - s) + s; if (n_p < 164) { return 0; } return w_arr[n_p - 164]; } /* Produces a "pseudo-random" number given seed 'x' */ static uint8_t pseudo_random(uint8_t x) { return (1103515245 * x + 12345) & 0xFF; // & 0xFF ensures the result is 0-255 } /* Produces a randomize "twinkle" effect. */ static uint8_t twinkle_raw(uint32_t time, size_t x, uint8_t amt) { uint8_t time_offset = pseudo_random(x); uint32_t adj_time = time - time_offset; uint32_t time8 = adj_time & 0xff; uint32_t speed = pseudo_random((adj_time >> 8) + x) & 0x3; time8 *= speed; if (time8 <= 255) { return calc_w(time8, amt); } else { return 0; } } uint8_t twinkle(uint32_t time, size_t x, uint8_t amt) { if (time % 2 == 0) { return twinkle_raw(time / 2, x, amt); } else { return (twinkle_raw(time / 2, x, amt) + twinkle_raw(time / 2 + 1, x, amt)) / 2; } }