smart_led_effects 0.1.8

A collection of effects for LED strips
Documentation
use crate::strip::EffectIterator;
use palette::{Mix, Srgb};
use std::time::{Duration, Instant};

pub struct Timer {
    count: usize,
    duration: Duration,
    start_colour: Srgb,
    end_colour: Srgb,
    gradient: bool,
    pixels_per_second: f32,
    start: Instant,
    running: bool,
}

impl Timer {
    const DEFAULT_START_COLOUR: Srgb = Srgb::new(0.0, 0.0, 1.0);
    const DEFAULT_END_COLOUR: Srgb = Srgb::new(1.0, 0.0, 0.0);
    pub fn new(
        count: usize,
        duration: Duration,
        start_colour: Option<Srgb>,
        end_colour: Option<Srgb>,
        gradient: Option<bool>,
        start: bool,
    ) -> Self {
        Timer {
            count,
            duration,
            start_colour: start_colour.unwrap_or(Self::DEFAULT_START_COLOUR),
            end_colour: end_colour.unwrap_or(Self::DEFAULT_END_COLOUR),
            gradient: gradient.unwrap_or(false),
            pixels_per_second: (count as f32) / (duration.as_millis() as f32 / 1000.0),
            start: Instant::now(),
            running: start,
        }
    }

    pub fn start(&mut self) {
        self.start = Instant::now();
        self.running = true;
    }

    pub fn stop(&mut self) {
        self.running = false;
    }

    pub fn reset(&mut self) {
        self.start = Instant::now();
    }
}

impl EffectIterator for Timer {
    fn name(&self) -> &'static str {
        "Timer"
    }

    fn next(&mut self) -> Option<Vec<Srgb<u8>>> {
        let mut out = vec![Srgb::new(0u8, 0u8, 0u8); self.count];
        let elapsed = self.start.elapsed().as_secs();
        if elapsed >= self.duration.as_secs() {
            self.reset();
            return Some(out);
        }
        let pixels = self.count - (self.pixels_per_second * elapsed as f32).ceil() as usize;
        if self.gradient {
            for (i, pixel) in out.iter_mut().take(pixels).enumerate() {
                *pixel = self
                    .end_colour
                    .mix(self.start_colour, i as f32 / self.count as f32)
                    .into_format();
            }
        } else {
            for pixel in out.iter_mut().take(pixels) {
                let mix = elapsed as f32 / self.duration.as_secs() as f32;
                *pixel = self.start_colour.mix(self.end_colour, mix).into_format();
            }
        }
        Some(out)
    }
}