feat: add animations!

This commit is contained in:
Jet Pham 2025-10-02 23:49:32 -07:00
parent d3874cc7ad
commit f3bcebc44c
No known key found for this signature in database
8 changed files with 124 additions and 32 deletions

13
src/animations/binary.rs Normal file
View file

@ -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
}

13
src/animations/mod.rs Normal file
View file

@ -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;

19
src/animations/ping.rs Normal file
View file

@ -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
}

10
src/animations/surge.rs Normal file
View file

@ -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]
}

20
src/animations/tyler.rs Normal file
View file

@ -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
}

17
src/animations/wave.rs Normal file
View file

@ -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
}

View file

@ -21,14 +21,16 @@ use panic_rtt_target as _;
extern crate alloc; 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!(); 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] #[main]
fn main() -> ! { fn main() -> ! {
@ -64,7 +66,7 @@ fn main() -> ! {
ledc.channel(channel::Number::Channel5, peripherals.GPIO21), ledc.channel(channel::Number::Channel5, peripherals.GPIO21),
]; ];
for channel in channels.iter_mut() { channels.iter_mut().for_each(|channel| {
channel channel
.configure(channel::config::Config { .configure(channel::config::Config {
timer: &lstimer0, timer: &lstimer0,
@ -72,37 +74,33 @@ fn main() -> ! {
pin_config: PinConfig::PushPull, pin_config: PinConfig::PushPull,
}) })
.unwrap(); .unwrap();
} });
let delay = Delay::new(); let delay = Delay::new();
let animations = [wave_animation, surge_animation, binary_animation, ping_animation, tyler_animation];
let mut angle: f32 = 0.0; let mut current_animation_index = 0;
let cycle_duration_ms = 1000; let mut animation_start_time = 0u32;
let steps_per_cycle = (cycle_duration_ms / 20) as u32; let animation_switch_interval_ms = 3000;
let angle_step = (2.0 * PI) / steps_per_cycle as f32; let frame_delay_ms = 10;
info!("Starting smooth sine wave LED brightness control (1 second cycle)...");
loop { loop {
for (i, channel) in channels.iter_mut().enumerate() { let current_animation = animations[current_animation_index];
let phase_offset = (i as f32) * (2.0 * PI) / 6.0; let led_values = current_animation(animation_start_time);
let led_angle = angle + phase_offset; info!("LED values: {:?}", led_values);
let brightness = calculate_sine_brightness(led_angle); channels.iter_mut()
let duty_pct = (brightness * 100.0) as u8; .zip(led_values.iter())
.for_each(|(channel, &duty_pct)| {
channel.set_duty(duty_pct).unwrap();
});
channel.set_duty(duty_pct).unwrap(); delay.delay_millis(frame_delay_ms);
animation_start_time += frame_delay_ms;
if i == 0 { if animation_start_time >= animation_switch_interval_ms {
info!("Base angle: {}, LED 0 brightness: {}%", angle, duty_pct); animation_start_time = 0;
} current_animation_index = (current_animation_index + 1) % animations.len();
} info!("Switching to animation {}", current_animation_index);
delay.delay_millis(20);
angle += angle_step;
if angle >= 2.0 * PI {
angle = 0.0;
} }
} }

View file

@ -1 +1,3 @@
#![no_std] #![no_std]
pub mod animations;