#include #include #include #include #include #include #define FPS 60 #define FRAME_DELAY_MS 1000 / FPS uint8_t random_step(uint8_t value, uint8_t min, uint8_t max, rng_t *rng) { int8_t step = (rng_sample(rng) % 20) - 10; int new_value = value + step; if (new_value > max) { return max; } else if (new_value < min) { return min; } else { return new_value; } } typedef enum { normal, creepy, } color_scheme_e; typedef struct { rgb_t lamp; color_scheme_e color_scheme; time_line_t red_line; time_line_t green_line; time_line_t blue_line; uint8_t frame; uint8_t duration; } animation_t; animation_t animation_new(void) { return (animation_t){ .lamp = (rgb_t){ .brightness = 1, .r = 200, .g = 30, .b = 0 }, .color_scheme = normal, .red_line = time_line_new(0, 0, 0, 0), .green_line = time_line_new(0, 0, 0, 0), .blue_line = time_line_new(0, 0, 0, 0), .frame = 0, .duration = 0, }; } void animation_flicker(animation_t *animation, rng_t *rng) { uint8_t rdest; uint8_t gdest; switch (animation->color_scheme) { case normal: rdest = random_step(animation->lamp.r, 180, 255, rng); gdest = random_step(animation->lamp.g, 20, 50, rng); animation->red_line = time_line_new(0, animation->lamp.r, 30, rdest); animation->green_line = time_line_new(0, animation->lamp.g, 30, gdest); animation->duration = 30; break; case creepy: break; } } void animation_step(animation_t *animation, rng_t *rng) { if (animation->duration == 0) { animation_flicker(animation, rng); } else { if (animation->frame == animation->duration) { animation->frame = 0; animation->duration = 0; } else { animation->frame++; animation->lamp.r = time_line_next(&animation->red_line); animation->lamp.g = time_line_next(&animation->green_line); animation->lamp.b = time_line_next(&animation->blue_line); } } } int main (void) { DDRB = _BV(2) | _BV(1) | _BV(0); PORTB = 0; _delay_ms(50); sk9822_t lights = { .data_pin = { .ddr = &DDRB, .port = &PORTB, .pin = &PINB, .addr = 0 }, .clock_pin = { .ddr = &DDRB, .port = &PORTB, .pin = &PINB, .addr = 2 } }; rng_t rng = rng_new(0); animation_t animation = animation_new(); while (1) { animation_step(&animation, &rng); sk9822_send(&lights, &animation.lamp, 1); _delay_ms(FRAME_DELAY_MS); } }