From 301496cf0e9db8645405d25672807d60f3e9b626 Mon Sep 17 00:00:00 2001 From: Savanni D'Gerinel Date: Fri, 5 Aug 2022 10:15:09 -0400 Subject: [PATCH] Extract the lantern animation code from main --- flake.nix | 13 --- lantern/lantern.c | 107 +++++++++++++++----- lantern/lantern.h | 32 +++++- lantern/main.c | 242 +--------------------------------------------- rng/rng.c | 24 ----- rng/rng.h | 18 ---- 6 files changed, 111 insertions(+), 325 deletions(-) delete mode 100644 rng/rng.c delete mode 100644 rng/rng.h diff --git a/flake.nix b/flake.nix index 715c36c..0328429 100644 --- a/flake.nix +++ b/flake.nix @@ -99,18 +99,6 @@ psrc = ./dio; }; - packages."x86_64-linux"."rng" = - { gcc, cflags }: - let - pkgs = import nixpkgs { system = "x86_64-linux"; }; - in mkLibrary { - pkgs = pkgs; - gcc = gcc; - cflags = cflags; - pname = "rng"; - psrc = ./rng; - }; - packages."x86_64-linux"."animation" = { gcc, cflags }: let @@ -258,7 +246,6 @@ (packages."x86_64-linux"."animation" { inherit gcc cflags; }) (packages."x86_64-linux"."dio" { inherit gcc cflags; }) (packages."x86_64-linux"."display" { inherit gcc cflags; }) - (packages."x86_64-linux"."rng" { inherit gcc cflags; }) (packages."x86_64-linux"."shift-register" { inherit gcc cflags; }) (packages."x86_64-linux"."sk9822" { inherit gcc cflags; }) ]; diff --git a/lantern/lantern.c b/lantern/lantern.c index 66195e3..37012a4 100644 --- a/lantern/lantern.c +++ b/lantern/lantern.c @@ -10,7 +10,62 @@ This AVR library is distributed in the hope that it will be useful, but WITHOUT You should have received a copy of the GNU General Public License along with this AVR library. If not, see . */ -#include +#include +#include +#include "lantern.h" + +uint8_t bound_uint8(int value, uint8_t min, uint8_t max) { + if (value > max) { + return max; + } else if (value < min) { + return min; + } else { + return value; + } +} + +uint8_t random_step(uint8_t value, uint8_t min, uint8_t max) { + int8_t step = (rand() % 40) - 20; + int new_value = value + step; + + return bound_uint8(new_value, min, max); +} + +animation_t animation_new(void) { + return (animation_t) { + .color = { .brightness = 1, .r = 0, .g = 0, .b = 0 }, + .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_begin(animation_t *self, uint8_t rdest, uint8_t gdest, uint8_t bdest, uint8_t duration) { + self->red_line = time_line_new(0, self->color.r, duration, rdest); + self->green_line = time_line_new(0, self->color.g, duration, gdest); + self->blue_line = time_line_new(0, self->color.b, duration, bdest); + self->frame = 0; + self->duration = duration; +} + +void animation_step(animation_t *self) { + if (self->frame == self->duration) { + self->frame = 0; + self->duration = 0; + } else { + self->frame++; + self->color.r = bound_uint8(time_line_next(&self->red_line), 0, 255); + self->color.g = bound_uint8(time_line_next(&self->green_line), 0, 255); + self->color.b = bound_uint8(time_line_next(&self->blue_line), 0, 255); + } +} + +bool animation_running(animation_t *self) { + return self->frame != self->duration; +} lantern_t lantern_new(sk9822_t lights) { sk9822_init(&lights); @@ -25,42 +80,42 @@ lantern_t lantern_new(sk9822_t lights) { }; } -void lantern_start_normal(lantern_t *self, rng_t *rng, int light_idx) { +void lantern_start_normal(lantern_t *self, int light_idx) { switch (light_idx) { case 0: animation_begin( &self->animations[0], - random_step(self->animations[0].color.r, 180, 255, rng), - random_step(self->animations[0].color.g, 20, 50, rng), + random_step(self->animations[0].color.r, 180, 255), + random_step(self->animations[0].color.g, 20, 50), 0, 5); break; case 1: animation_begin( &self->animations[1], - random_step(self->animations[1].color.r, 160, 230, rng), - random_step(self->animations[1].color.g, 10, 30, rng), + random_step(self->animations[1].color.r, 160, 230), + random_step(self->animations[1].color.g, 10, 30), 0, 15); break; case 2: animation_begin( &self->animations[2], - random_step(self->animations[2].color.r, 140, 170, rng), - random_step(self->animations[2].color.g, 0, 10, rng), + random_step(self->animations[2].color.r, 140, 170), + random_step(self->animations[2].color.g, 0, 10), 0, 30); break; } } -void lantern_start_spooky(lantern_t *self, rng_t *rng, int light_idx) { +void lantern_start_spooky(lantern_t *self, int light_idx) { switch (light_idx) { case 0: animation_begin( &self->animations[0], 0, - random_step(self->animations[0].color.g, 80, 120, rng), + random_step(self->animations[0].color.g, 80, 120), 0, 15); break; @@ -68,7 +123,7 @@ void lantern_start_spooky(lantern_t *self, rng_t *rng, int light_idx) { animation_begin( &self->animations[1], 0, - random_step(self->animations[1].color.g, 60, 100, rng), + random_step(self->animations[1].color.g, 60, 100), 0, 15); break; @@ -76,37 +131,37 @@ void lantern_start_spooky(lantern_t *self, rng_t *rng, int light_idx) { animation_begin( &self->animations[2], 0, - random_step(self->animations[2].color.g, 20, 40, rng), + random_step(self->animations[2].color.g, 20, 40), 0, 15); break; } } -void lantern_start_eerie(lantern_t *self, rng_t *rng, int light_idx) { +void lantern_start_eerie(lantern_t *self, int light_idx) { switch (light_idx) { case 0: animation_begin( &self->animations[0], - random_step(self->animations[0].color.g, 20, 40, rng), - random_step(self->animations[0].color.g, 20, 40, rng), - random_step(self->animations[0].color.g, 80, 120, rng), + random_step(self->animations[0].color.g, 20, 40), + random_step(self->animations[0].color.g, 20, 40), + random_step(self->animations[0].color.g, 80, 120), 15); break; case 1: animation_begin( &self->animations[1], - random_step(self->animations[0].color.g, 0, 30, rng), - random_step(self->animations[0].color.g, 0, 30, rng), - random_step(self->animations[1].color.g, 60, 100, rng), + random_step(self->animations[0].color.g, 0, 30), + random_step(self->animations[0].color.g, 0, 30), + random_step(self->animations[1].color.g, 60, 100), 30); break; case 2: animation_begin( &self->animations[2], - random_step(self->animations[0].color.g, 0, 10, rng), - random_step(self->animations[0].color.g, 0, 10, rng), - random_step(self->animations[2].color.g, 20, 40, rng), + random_step(self->animations[0].color.g, 0, 10), + random_step(self->animations[0].color.g, 0, 10), + random_step(self->animations[2].color.g, 20, 40), 45); break; } @@ -116,18 +171,18 @@ void lantern_set_mode(lantern_t *self, color_scheme_e scheme) { self->color_scheme = scheme; } -void lantern_step(lantern_t *self, display_t *display, rng_t *rng, rgb_t colors[LIGHT_COUNT]) { +void lantern_step(lantern_t *self, rgb_t colors[LIGHT_COUNT]) { for (int i = 0; i < LIGHT_COUNT; i++) { if (!animation_running(&self->animations[i])) { switch (self->color_scheme) { case normal: - lantern_start_normal(self, rng, i); + lantern_start_normal(self, i); break; case spooky: - lantern_start_spooky(self, rng, i); + lantern_start_spooky(self, i); break; case eerie: - lantern_start_eerie(self, rng, i); + lantern_start_eerie(self, i); break; case flash: break; diff --git a/lantern/lantern.h b/lantern/lantern.h index a5c235a..51585cc 100644 --- a/lantern/lantern.h +++ b/lantern/lantern.h @@ -10,10 +10,32 @@ This AVR library is distributed in the hope that it will be useful, but WITHOUT You should have received a copy of the GNU General Public License along with this AVR library. If not, see . */ +#include +#include +#include + #ifndef __LANTERN_H__ #define __LANTERN_H__ -#include +#define LIGHT_COUNT 3 + +typedef struct { + rgb_t color; + + time_line_t red_line; + time_line_t green_line; + time_line_t blue_line; + + uint8_t frame; + uint8_t duration; +} animation_t; + +typedef enum { + normal, + spooky, + eerie, + flash +} color_scheme_e; typedef struct { sk9822_t lights; @@ -22,11 +44,11 @@ typedef struct { animation_t animations[LIGHT_COUNT]; } lantern_t; -lantern_t lantern_new(sk9822_t lights) { -void lantern_set_mode(lantern_t *self, color_scheme_e scheme); -void lantern_step(lantern_t *self, display_t *display, rng_t *rng, rgb_t colors[LIGHT_COUNT]); +lantern_t lantern_new(sk9822_t); +void lantern_set_mode(lantern_t *, color_scheme_e); +void lantern_step(lantern_t *, rgb_t *); -void lantern_show(lantern_t *lantern, display_t *display); +void lantern_show(lantern_t *, display_t *); #endif diff --git a/lantern/main.c b/lantern/main.c index 9e49302..4d0d5d0 100644 --- a/lantern/main.c +++ b/lantern/main.c @@ -10,21 +10,19 @@ This AVR library is distributed in the hope that it will be useful, but WITHOUT You should have received a copy of the GNU General Public License along with this AVR library. If not, see . */ -#include #include #include #include #include -#include #include #include #include #include +#include "lantern.h" #define FPS 15 #define TICKS_PER_SECOND 7812 #define FPS_TIMEOUT TICKS_PER_SECOND / FPS -#define LIGHT_COUNT 3 #define PULSE_OFF_COUNT FPS * 5 #define PULSE_ON_COUNT 5 @@ -38,238 +36,6 @@ ISR(TIMER1_COMPA_vect) { */ } -typedef enum { - normal, - spooky, - eerie, - flash -} color_scheme_e; - -uint8_t bound_uint8(int value, uint8_t min, uint8_t max) { - if (value > max) { - return max; - } else if (value < min) { - return min; - } else { - return value; - } -} - -uint8_t random_step(uint8_t value, uint8_t min, uint8_t max, rng_t *rng) { - int8_t step = (rand() % 40) - 20; - int new_value = value + step; - - return bound_uint8(new_value, min, max); -} - -typedef struct { - rgb_t color; - - 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) { - .color = { .brightness = 1, .r = 0, .g = 0, .b = 0 }, - .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_begin(animation_t *self, uint8_t rdest, uint8_t gdest, uint8_t bdest, uint8_t duration) { - self->red_line = time_line_new(0, self->color.r, duration, rdest); - self->green_line = time_line_new(0, self->color.g, duration, gdest); - self->blue_line = time_line_new(0, self->color.b, duration, bdest); - self->frame = 0; - self->duration = duration; -} - -void animation_step(animation_t *self) { - if (self->frame == self->duration) { - self->frame = 0; - self->duration = 0; - } else { - self->frame++; - self->color.r = bound_uint8(time_line_next(&self->red_line), 0, 255); - self->color.g = bound_uint8(time_line_next(&self->green_line), 0, 255); - self->color.b = bound_uint8(time_line_next(&self->blue_line), 0, 255); - } -} - -bool animation_running(animation_t *self) { - return self->frame != self->duration; -} - -typedef struct { - sk9822_t lights; - - color_scheme_e color_scheme; - animation_t animations[LIGHT_COUNT]; -} lantern_t; - -void display_lantern(display_t *display, lantern_t *lantern); - -lantern_t lantern_new(sk9822_t lights) { - sk9822_init(&lights); - return (lantern_t){ - .lights = lights, - .color_scheme = normal, - .animations = { - animation_new(), - animation_new(), - animation_new(), - } - }; -} - -void lantern_start_normal(lantern_t *self, rng_t *rng, int light_idx) { - switch (light_idx) { - case 0: - animation_begin( - &self->animations[0], - random_step(self->animations[0].color.r, 180, 255, rng), - random_step(self->animations[0].color.g, 20, 50, rng), - 0, - 5); - break; - case 1: - animation_begin( - &self->animations[1], - random_step(self->animations[1].color.r, 160, 230, rng), - random_step(self->animations[1].color.g, 10, 30, rng), - 0, - 15); - break; - case 2: - animation_begin( - &self->animations[2], - random_step(self->animations[2].color.r, 140, 170, rng), - random_step(self->animations[2].color.g, 0, 10, rng), - 0, - 30); - break; - } -} - -void lantern_start_spooky(lantern_t *self, rng_t *rng, int light_idx) { - switch (light_idx) { - case 0: - animation_begin( - &self->animations[0], - 0, - random_step(self->animations[0].color.g, 80, 120, rng), - 0, - 15); - break; - case 1: - animation_begin( - &self->animations[1], - 0, - random_step(self->animations[1].color.g, 60, 100, rng), - 0, - 15); - break; - case 2: - animation_begin( - &self->animations[2], - 0, - random_step(self->animations[2].color.g, 20, 40, rng), - 0, - 15); - break; - } -} - -void lantern_start_eerie(lantern_t *self, rng_t *rng, int light_idx) { - switch (light_idx) { - case 0: - animation_begin( - &self->animations[0], - random_step(self->animations[0].color.g, 20, 40, rng), - random_step(self->animations[0].color.g, 20, 40, rng), - random_step(self->animations[0].color.g, 80, 120, rng), - 15); - break; - case 1: - animation_begin( - &self->animations[1], - random_step(self->animations[0].color.g, 0, 30, rng), - random_step(self->animations[0].color.g, 0, 30, rng), - random_step(self->animations[1].color.g, 60, 100, rng), - 30); - break; - case 2: - animation_begin( - &self->animations[2], - random_step(self->animations[0].color.g, 0, 10, rng), - random_step(self->animations[0].color.g, 0, 10, rng), - random_step(self->animations[2].color.g, 20, 40, rng), - 45); - break; - } -} - -void lantern_set_mode(lantern_t *self, color_scheme_e scheme) { - self->color_scheme = scheme; -} - -void lantern_step(lantern_t *self, display_t *display, rng_t *rng, rgb_t colors[LIGHT_COUNT]) { - for (int i = 0; i < LIGHT_COUNT; i++) { - if (!animation_running(&self->animations[i])) { - switch (self->color_scheme) { - case normal: - lantern_start_normal(self, rng, i); - break; - case spooky: - lantern_start_spooky(self, rng, i); - break; - case eerie: - lantern_start_eerie(self, rng, i); - break; - case flash: - break; - } - } - - animation_step(&self->animations[i]); - colors[i] = self->animations[i].color; - } -} - -void display_lantern(display_t *display, lantern_t *lantern) { - char msg1[20]; - char msg2[20]; - - snprintf(msg1, 20, "[%d,%d] %x,%x,%x", - lantern->animations[0].frame, - lantern->animations[0].duration, - lantern->animations[0].color.r, - lantern->animations[0].color.g, - lantern->animations[0].color.b - ); - snprintf(msg2, 20, "%x,%x,%x %x,%x,%x", - lantern->animations[1].color.r, - lantern->animations[1].color.g, - lantern->animations[1].color.b, - lantern->animations[2].color.r, - lantern->animations[2].color.g, - lantern->animations[2].color.b - ); - display_clear(display); - display_write_message(display, msg1); - display_set_location(display, 1, 0); - display_write_message(display, msg2); -} - typedef struct { bool on; int timeout; @@ -329,9 +95,7 @@ int main(void) { lantern_t lantern = lantern_new(lights); lantern_set_mode(&lantern, normal); - rng_t rng = rng_new(15); - - lantern_step(&lantern, &display, &rng, colors); + lantern_step(&lantern, colors); sk9822_send(&lights, colors, LIGHT_COUNT); // power_pulse_t timer = { .on = false, .timeout = PULSE_OFF_COUNT }; @@ -340,7 +104,7 @@ int main(void) { set_sleep_mode(SLEEP_MODE_IDLE); while(1) { - lantern_step(&lantern, &display, &rng, colors); + lantern_step(&lantern, colors); sk9822_send(&lights, colors, LIGHT_COUNT); sei(); diff --git a/rng/rng.c b/rng/rng.c deleted file mode 100644 index ac4a067..0000000 --- a/rng/rng.c +++ /dev/null @@ -1,24 +0,0 @@ -/* -Copyright 2022, Savanni D'Gerinel - -This file is part of Savanni's AVR library. - -Lumeto is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. - -Lumeto is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. - -You should have received a copy of the GNU General Public License along with Lumeto. If not, see . -*/ - -#include "rng.h" - -rng_t rng_new(uint8_t seed) { - rng_t rng = { .mod = 255, .a = 253, .c = 41, .seed = seed }; - return rng; -} - -uint8_t rng_sample(rng_t *state) { - state->seed = (state->a * state->seed + state->c) % state->mod; - return state->seed; -} - diff --git a/rng/rng.h b/rng/rng.h deleted file mode 100644 index 6dd187f..0000000 --- a/rng/rng.h +++ /dev/null @@ -1,18 +0,0 @@ - -#include - -#ifndef __RNG_H__ -#define __RNG_H__ - -typedef struct RNG { - uint8_t mod; - int8_t a; - int8_t c; - uint8_t seed; -} rng_t; - -rng_t rng_new(uint8_t seed); - -uint8_t rng_sample(rng_t *state); - -#endif