From 6327e31e52b208003c566769bcf2e606f67144ea Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Franti=C5=A1ek=20Boh=C3=A1=C4=8Dek?= Date: Sun, 25 Jun 2023 20:19:15 +0200 Subject: [PATCH] feat: add snake animation command --- src/animations/snake_animation.rs | 25 +++++++++++-- src/commands.rs | 3 +- src/commands/snake_command.rs | 58 +++++++++++++++++++++++++++++++ 3 files changed, 83 insertions(+), 3 deletions(-) create mode 100644 src/commands/snake_command.rs diff --git a/src/animations/snake_animation.rs b/src/animations/snake_animation.rs index 74e0e5e..bd3240e 100644 --- a/src/animations/snake_animation.rs +++ b/src/animations/snake_animation.rs @@ -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 { step: usize, + finished: bool, order: [usize; LEDS_COUNT], previous_factor: f32, color: RGB8, @@ -17,12 +20,21 @@ impl SnakeAnimation { 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 Animation for SnakeAnimation { @@ -35,7 +47,8 @@ impl Animation for SnakeAnimation { } fn next(&mut self) -> Result { - if self.step == LEDS_COUNT - 1 { + if self.step == LEDS_COUNT + 100 { + self.finished = true; return Err(AnimationError::LastStep); } @@ -44,7 +57,11 @@ impl Animation for SnakeAnimation { } 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 Animation for SnakeAnimation { map.set(*led_index, color).ok().unwrap(); } + if self.is_last_step() { + map.clear(); + } + Ok(()) } } \ No newline at end of file diff --git a/src/commands.rs b/src/commands.rs index 0d2f130..7fcafc5 100644 --- a/src/commands.rs +++ b/src/commands.rs @@ -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 diff --git a/src/commands/snake_command.rs b/src/commands/snake_command.rs new file mode 100644 index 0000000..4e6e768 --- /dev/null +++ b/src/commands/snake_command.rs @@ -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 { + " - Let snake run with the given base color and coefficient of light off" + } +} \ No newline at end of file -- 2.48.1