diff --git a/src/animations/binary.rs b/src/animations/binary.rs new file mode 100644 index 0000000..e8e731e --- /dev/null +++ b/src/animations/binary.rs @@ -0,0 +1,13 @@ +pub fn binary_animation(time_ms: u32) -> [u8; 6] { + let increment_interval_ms = 1000.0 / 64.0; + let count = (time_ms as f32 / increment_interval_ms) as u32 % 64; + + let mut leds = [0u8; 6]; + (0..6).for_each(|i| { + if count & (1 << i) != 0 { + leds[5-i] = 100; + } + }); + + leds +} diff --git a/src/animations/mod.rs b/src/animations/mod.rs new file mode 100644 index 0000000..ae1b4b6 --- /dev/null +++ b/src/animations/mod.rs @@ -0,0 +1,13 @@ +pub type AnimationFunction = fn(u32) -> [u8; 6]; + +pub mod wave; +pub mod surge; +pub mod ping; +pub mod binary; +pub mod tyler; + +pub use wave::wave_animation; +pub use surge::surge_animation; +pub use ping::ping_animation; +pub use binary::binary_animation; +pub use tyler::tyler_animation; diff --git a/src/animations/ping.rs b/src/animations/ping.rs new file mode 100644 index 0000000..d7293dd --- /dev/null +++ b/src/animations/ping.rs @@ -0,0 +1,19 @@ +pub fn ping_animation(time_ms: u32) -> [u8; 6] { + let cycle_duration_ms = 1000; + let cycle_position = (time_ms % cycle_duration_ms) as f32 / cycle_duration_ms as f32; + + let mut leds = [0u8; 6]; + + let led_index = if cycle_position < 6.0 / 10.0 { + (cycle_position * 10.0) as usize + } else { + (10.0 - (cycle_position * 10.0)) as usize + }; + + // Ensure we don't go out of bounds + if led_index < 6 { + leds[led_index] = 100; + } + + leds +} diff --git a/src/animations/surge.rs b/src/animations/surge.rs new file mode 100644 index 0000000..9f522d6 --- /dev/null +++ b/src/animations/surge.rs @@ -0,0 +1,10 @@ +use core::f32::consts::PI; + +pub fn surge_animation(time_ms: u32) -> [u8; 6] { + let cycle_duration_ms = 2000; + let angle = (time_ms as f32 / cycle_duration_ms as f32) * 2.0 * PI; + let sine_value = libm::sinf(angle); + let brightness = (sine_value + 1.0) / 2.0; + let duty = (brightness * 100.0) as u8; + [duty; 6] +} diff --git a/src/animations/tyler.rs b/src/animations/tyler.rs new file mode 100644 index 0000000..4618062 --- /dev/null +++ b/src/animations/tyler.rs @@ -0,0 +1,20 @@ +use core::f32::consts::PI; +use defmt::info; + +pub fn tyler_animation(time_ms: u32) -> [u8; 6] { + let cycle_duration_ms = 3000; + let angle = (time_ms as f32 / cycle_duration_ms as f32) * 2.0 * PI; + + let mut leds = [0u8; 6]; + leds.iter_mut().enumerate().for_each(|(i, led)| { + let sine_value = (1..i+2).fold(1.0, |acc, i| { + let b = i as f32; + acc * libm::sinf(b * angle + (b * 0.5)) - 0.1 + }); + info!("{:?}", sine_value); + let brightness = sine_value.max(0.0); + *led = (brightness * 100.0) as u8; + }); + + leds +} diff --git a/src/animations/wave.rs b/src/animations/wave.rs new file mode 100644 index 0000000..303950f --- /dev/null +++ b/src/animations/wave.rs @@ -0,0 +1,17 @@ +use core::f32::consts::PI; + +pub fn wave_animation(time_ms: u32) -> [u8; 6] { + let cycle_duration_ms = 1000; + let angle = (time_ms as f32 / cycle_duration_ms as f32) * 2.0 * PI; + + let mut leds = [0u8; 6]; + leds.iter_mut().enumerate().for_each(|(i, led)| { + let phase_offset = (i as f32) * (2.0 * PI) / 6.0; + let led_angle = angle + phase_offset; + let sine_value = libm::sinf(led_angle); + let brightness = (sine_value + 1.0) / 2.0; + *led = (brightness * 100.0) as u8; + }); + + leds +} diff --git a/src/bin/main.rs b/src/bin/main.rs index 3e4882f..2277f45 100644 --- a/src/bin/main.rs +++ b/src/bin/main.rs @@ -21,14 +21,16 @@ use panic_rtt_target as _; extern crate alloc; -use core::f32::consts::PI; +use firebeetle_2_board_esp32_c6::animations::{ + wave::wave_animation, + surge::surge_animation, + ping::ping_animation, + binary::binary_animation, + tyler::tyler_animation +}; esp_bootloader_esp_idf::esp_app_desc!(); -fn calculate_sine_brightness(angle: f32) -> f32 { - let sine_value = libm::sinf(angle); - (sine_value + 1.0) / 2.0 -} #[main] fn main() -> ! { @@ -64,7 +66,7 @@ fn main() -> ! { ledc.channel(channel::Number::Channel5, peripherals.GPIO21), ]; - for channel in channels.iter_mut() { + channels.iter_mut().for_each(|channel| { channel .configure(channel::config::Config { timer: &lstimer0, @@ -72,37 +74,33 @@ fn main() -> ! { pin_config: PinConfig::PushPull, }) .unwrap(); - } + }); let delay = Delay::new(); - - let mut angle: f32 = 0.0; - let cycle_duration_ms = 1000; - let steps_per_cycle = (cycle_duration_ms / 20) as u32; - let angle_step = (2.0 * PI) / steps_per_cycle as f32; - - info!("Starting smooth sine wave LED brightness control (1 second cycle)..."); + let animations = [wave_animation, surge_animation, binary_animation, ping_animation, tyler_animation]; + let mut current_animation_index = 0; + let mut animation_start_time = 0u32; + let animation_switch_interval_ms = 3000; + let frame_delay_ms = 10; loop { - for (i, channel) in channels.iter_mut().enumerate() { - let phase_offset = (i as f32) * (2.0 * PI) / 6.0; - let led_angle = angle + phase_offset; + let current_animation = animations[current_animation_index]; + let led_values = current_animation(animation_start_time); + info!("LED values: {:?}", led_values); + + channels.iter_mut() + .zip(led_values.iter()) + .for_each(|(channel, &duty_pct)| { + channel.set_duty(duty_pct).unwrap(); + }); - let brightness = calculate_sine_brightness(led_angle); - let duty_pct = (brightness * 100.0) as u8; - - channel.set_duty(duty_pct).unwrap(); - - if i == 0 { - info!("Base angle: {}, LED 0 brightness: {}%", angle, duty_pct); - } - } - - delay.delay_millis(20); - - angle += angle_step; - if angle >= 2.0 * PI { - angle = 0.0; + delay.delay_millis(frame_delay_ms); + animation_start_time += frame_delay_ms; + + if animation_start_time >= animation_switch_interval_ms { + animation_start_time = 0; + current_animation_index = (current_animation_index + 1) % animations.len(); + info!("Switching to animation {}", current_animation_index); } } diff --git a/src/lib.rs b/src/lib.rs index 0c9ac1a..2bbf215 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -1 +1,3 @@ #![no_std] + +pub mod animations;