~ruther/map-led-strip

6327e31e52b208003c566769bcf2e606f67144ea — František Boháček 1 year, 9 months ago b0fe6c3
feat: add snake animation command
3 files changed, 83 insertions(+), 3 deletions(-)

M src/animations/snake_animation.rs
M src/commands.rs
A src/commands/snake_command.rs
M src/animations/snake_animation.rs => src/animations/snake_animation.rs +23 -2
@@ 1,3 1,5 @@
use core::cmp::max;
use esp_println::println;
use fugit::MicrosDurationU64;
use libm::{ceilf, powf};
use smart_leds::RGB8;


@@ 7,6 9,7 @@ use crate::map::Map;

pub struct SnakeAnimation<const LEDS_COUNT: usize> {
    step: usize,
    finished: bool,
    order: [usize; LEDS_COUNT],
    previous_factor: f32,
    color: RGB8,


@@ 17,12 20,21 @@ impl<const LEDS_COUNT: usize> SnakeAnimation<LEDS_COUNT> {
    pub fn new(order: [usize; LEDS_COUNT], previous_factor: f32, color: RGB8, step_duration: MicrosDurationU64) -> Self {
        Self {
            step: 0,
            finished: false,
            order,
            previous_factor,
            color,
            step_duration
        }
    }

    fn is_first_step(&self) -> bool {
        self.step == 1
    }

    fn is_last_step(&self) -> bool {
        self.finished
    }
}

impl<const LEDS_COUNT: usize> Animation for SnakeAnimation<LEDS_COUNT> {


@@ 35,7 47,8 @@ impl<const LEDS_COUNT: usize> Animation for SnakeAnimation<LEDS_COUNT> {
    }

    fn next(&mut self) -> Result<AnimationStep, AnimationError> {
        if self.step == LEDS_COUNT - 1 {
        if self.step == LEDS_COUNT + 100 {
            self.finished = true;
            return Err(AnimationError::LastStep);
        }



@@ 44,7 57,11 @@ impl<const LEDS_COUNT: usize> Animation for SnakeAnimation<LEDS_COUNT> {
    }

    fn apply(&mut self, map: &mut Map) -> Result<(), AnimationError> {
        for (i, led_index) in self.order.iter().take(self.step).enumerate() {
        if self.is_first_step() {
            map.clear();
        }

        for (i, led_index) in self.order.iter().take(self.step.max(LEDS_COUNT)).enumerate() {
            let mult_factor = self.step - i - 1;
            let coeff = powf(self.previous_factor, mult_factor as f32);
            let rgb = self.color;


@@ 57,6 74,10 @@ impl<const LEDS_COUNT: usize> Animation for SnakeAnimation<LEDS_COUNT> {
            map.set(*led_index, color).ok().unwrap();
        }

        if self.is_last_step() {
            map.clear();
        }

        Ok(())
    }
}
\ No newline at end of file

M src/commands.rs => src/commands.rs +2 -1
@@ 5,4 5,5 @@ pub mod command_argument;
pub mod set_command;
pub mod reset_command;
pub mod all_command;
pub mod command_data;
\ No newline at end of file
pub mod command_data;
pub mod snake_command;
\ No newline at end of file

A src/commands/snake_command.rs => src/commands/snake_command.rs +58 -0
@@ 0,0 1,58 @@
use esp_println::println;
use fugit::ExtU64;
use smart_leds::RGB8;
use crate::animations::snake_animation::SnakeAnimation;
use crate::commands::command_data::CommandData;
use crate::commands::command_handler::{CommandHandleError, SpecificCommandHandler};
use crate::commands::command_handler::CommandHandleError::WrongArguments;
use crate::constants;

#[derive(Default)]
pub struct SnakeCommand;

impl SpecificCommandHandler for SnakeCommand {
    fn handle(&self, command: CommandData) -> Result<(), CommandHandleError> {
        let (cmd, animation) = command.deconstruct_animation();

        if cmd.parsed_arguments().len() < 6 {
            println!("Less than 6 args.");
            return Err(WrongArguments);
        }

        let coeff = cmd.parsed_arguments()[1].try_to_integer();

        let r = cmd.parsed_arguments()[2].try_to_integer();
        let g = cmd.parsed_arguments()[3].try_to_integer();
        let b = cmd.parsed_arguments()[4].try_to_integer();
        let duration = cmd.parsed_arguments()[5].try_to_integer();

        if r.is_none() || g.is_none() || b.is_none() || coeff.is_none() || duration.is_none() {
            println!("Cold not parse r, g, b, coeff or duration.");
            return Err(WrongArguments);
        }

        let coeff = coeff.unwrap();
        let r = r.unwrap();
        let g = g.unwrap();
        let b = b.unwrap();
        let duration = duration.unwrap();

        if r > 255 || g > 255 || b > 255 || coeff > 255 {
            return Err(WrongArguments);
        }
        let coeff = coeff as f32 / 255.0;

        animation
            .set_animation(SnakeAnimation::<{ constants::LEDS_COUNT }>::new(
                [24, 19, 16, 10, 15, 9, 6, 8, 3, 0, 4, 1, 2, 5, 11, 7, 12, 18, 21, 29, 27, 34, 38, 31, 17, 25, 45, 30, 36, 35, 42, 44, 56, 48, 61, 57, 65, 68, 59, 49, 55, 63, 71, 69, 62, 47, 53, 46, 51, 64, 52, 67, 70, 66, 60, 58, 54, 50, 37, 40, 41, 23, 22, 14, 13, 20, 28, 33, 39, 43, 32, 26],
                coeff,
                RGB8 { r: r as u8, g: g as u8, b: b as u8 },
                (duration as u64 * 1000u64).micros())
            );
        Ok(())
    }

    fn help(&self) -> &'static str {
        "<coeff> <R> <G> <B> <duration> - Let snake run with the given base color and coefficient of light off"
    }
}
\ No newline at end of file

Do not follow this link