feat: expand into 8 leds

This commit is contained in:
Jet Pham 2025-10-03 14:35:03 -07:00
parent f3bcebc44c
commit dab048d301
No known key found for this signature in database
7 changed files with 95 additions and 106 deletions

View file

@ -1,11 +1,11 @@
pub fn binary_animation(time_ms: u32) -> [u8; 6] { pub fn binary_animation(time_ms: u32) -> [u8; 8] {
let increment_interval_ms = 1000.0 / 64.0; let increment_interval_ms = 3000 / 256;
let count = (time_ms as f32 / increment_interval_ms) as u32 % 64; let count = (time_ms / increment_interval_ms) % 256;
let mut leds = [0u8; 6]; let mut leds = [0u8; 8];
(0..6).for_each(|i| { (0..8).for_each(|i| {
if count & (1 << i) != 0 { if count & (1 << i) != 0 {
leds[5-i] = 100; leds[7-i] = 100;
} }
}); });

View file

@ -1,13 +1,11 @@
pub type AnimationFunction = fn(u32) -> [u8; 6]; pub type AnimationFunction = fn(u32) -> [u8; 8];
pub mod wave; pub mod wave;
pub mod surge; pub mod surge;
pub mod ping; pub mod ping;
pub mod binary; pub mod binary;
pub mod tyler;
pub use wave::wave_animation; pub use wave::wave_animation;
pub use surge::surge_animation; pub use surge::surge_animation;
pub use ping::ping_animation; pub use ping::ping_animation;
pub use binary::binary_animation; pub use binary::binary_animation;
pub use tyler::tyler_animation;

View file

@ -1,17 +1,16 @@
pub fn ping_animation(time_ms: u32) -> [u8; 6] { pub fn ping_animation(time_ms: u32) -> [u8; 8] {
let cycle_duration_ms = 1000; let cycle_duration_ms = 1000;
let cycle_position = (time_ms % cycle_duration_ms) as f32 / cycle_duration_ms as f32; let cycle_position = (time_ms % cycle_duration_ms) as f32 / cycle_duration_ms as f32;
let mut leds = [0u8; 6]; let mut leds = [0u8; 8];
let led_index = if cycle_position < 6.0 / 10.0 { let led_index = if cycle_position < 8.0 / 14.0 {
(cycle_position * 10.0) as usize (cycle_position * 14.0) as usize
} else { } else {
(10.0 - (cycle_position * 10.0)) as usize (14.0 - (cycle_position * 14.0)) as usize
}; };
// Ensure we don't go out of bounds if led_index < 8 {
if led_index < 6 {
leds[led_index] = 100; leds[led_index] = 100;
} }

View file

@ -1,10 +1,10 @@
use core::f32::consts::PI; use core::f32::consts::PI;
pub fn surge_animation(time_ms: u32) -> [u8; 6] { pub fn surge_animation(time_ms: u32) -> [u8; 8] {
let cycle_duration_ms = 2000; let cycle_duration_ms = 2000;
let angle = (time_ms as f32 / cycle_duration_ms as f32) * 2.0 * PI; let angle = (time_ms as f32 / cycle_duration_ms as f32) * 2.0 * PI;
let sine_value = libm::sinf(angle); let sine_value = libm::sinf(angle);
let brightness = (sine_value + 1.0) / 2.0; let brightness = (sine_value + 1.0) / 2.0;
let duty = (brightness * 100.0) as u8; let duty = (brightness * 100.0) as u8;
[duty; 6] [duty; 8]
} }

View file

@ -1,20 +0,0 @@
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
}

View file

@ -1,12 +1,12 @@
use core::f32::consts::PI; use core::f32::consts::PI;
pub fn wave_animation(time_ms: u32) -> [u8; 6] { pub fn wave_animation(time_ms: u32) -> [u8; 8] {
let cycle_duration_ms = 1000; let cycle_duration_ms = 1000;
let angle = (time_ms as f32 / cycle_duration_ms as f32) * 2.0 * PI; let angle = (time_ms as f32 / cycle_duration_ms as f32) * 2.0 * PI;
let mut leds = [0u8; 6]; let mut leds = [0u8; 8];
leds.iter_mut().enumerate().for_each(|(i, led)| { leds.iter_mut().enumerate().for_each(|(i, led)| {
let phase_offset = (i as f32) * (2.0 * PI) / 6.0; let phase_offset = (i as f32) * (2.0 * PI) / 8.0;
let led_angle = angle + phase_offset; let led_angle = angle + phase_offset;
let sine_value = libm::sinf(led_angle); let sine_value = libm::sinf(led_angle);
let brightness = (sine_value + 1.0) / 2.0; let brightness = (sine_value + 1.0) / 2.0;

View file

@ -6,35 +6,54 @@
holding buffers for the duration of a data transfer." holding buffers for the duration of a data transfer."
)] )]
use defmt::info; use esp_hal::{
use esp_hal::clock::CpuClock; clock::CpuClock,
use esp_hal::delay::Delay; gpio::{Level, Output, OutputConfig},
use esp_hal::ledc::{ main,
channel::{self, config::PinConfig, ChannelIFace}, time::{Duration, Instant},
timer::{self, config::Duty, LSClockSource, TimerIFace}, timer::timg::TimerGroup,
LSGlobalClkSource, Ledc, LowSpeed,
}; };
use esp_hal::main;
use esp_hal::time::Rate;
use esp_hal::timer::timg::TimerGroup;
use panic_rtt_target as _; use panic_rtt_target as _;
extern crate alloc; extern crate alloc;
use firebeetle_2_board_esp32_c6::animations::{ use firebeetle_2_board_esp32_c6::animations::{
wave::wave_animation, binary::binary_animation, ping::ping_animation, surge::surge_animation, 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!();
struct SoftwarePWM {
duty_cycles: [u16; 8],
pwm_period: u16,
current_step: u16,
}
impl SoftwarePWM {
fn new() -> Self {
Self {
duty_cycles: [0; 8],
pwm_period: 2000,
current_step: 0,
}
}
fn set_duty_cycles(&mut self, duty_cycles: [u8; 8]) {
for (i, &duty) in duty_cycles.iter().enumerate() {
self.duty_cycles[i] = (duty as u16 * 20).min(2000);
}
}
fn should_be_high(&self, led_index: usize) -> bool {
self.current_step < self.duty_cycles[led_index]
}
fn update_step(&mut self) {
self.current_step = (self.current_step + 1) % self.pwm_period;
}
}
#[main] #[main]
fn main() -> ! { fn main() -> ! {
rtt_target::rtt_init_defmt!(); rtt_target::rtt_init_defmt!();
let config = esp_hal::Config::default().with_cpu_clock(CpuClock::max()); let config = esp_hal::Config::default().with_cpu_clock(CpuClock::max());
@ -45,63 +64,56 @@ fn main() -> ! {
let timg0 = TimerGroup::new(peripherals.TIMG0); let timg0 = TimerGroup::new(peripherals.TIMG0);
let _init = esp_wifi::init(timg0.timer0, esp_hal::rng::Rng::new(peripherals.RNG)).unwrap(); let _init = esp_wifi::init(timg0.timer0, esp_hal::rng::Rng::new(peripherals.RNG)).unwrap();
let mut ledc = Ledc::new(peripherals.LEDC); let mut leds = [
ledc.set_global_slow_clock(LSGlobalClkSource::APBClk); Output::new(peripherals.GPIO1, Level::Low, OutputConfig::default()),
Output::new(peripherals.GPIO18, Level::Low, OutputConfig::default()),
let mut lstimer0 = ledc.timer::<LowSpeed>(timer::Number::Timer0); Output::new(peripherals.GPIO9, Level::Low, OutputConfig::default()),
lstimer0 Output::new(peripherals.GPIO19, Level::Low, OutputConfig::default()),
.configure(timer::config::Config { Output::new(peripherals.GPIO20, Level::Low, OutputConfig::default()),
duty: Duty::Duty8Bit, Output::new(peripherals.GPIO21, Level::Low, OutputConfig::default()),
clock_source: LSClockSource::APBClk, Output::new(peripherals.GPIO22, Level::Low, OutputConfig::default()),
frequency: Rate::from_hz(1000), Output::new(peripherals.GPIO23, Level::Low, OutputConfig::default()),
})
.unwrap();
let mut channels = [
ledc.channel(channel::Number::Channel0, peripherals.GPIO1),
ledc.channel(channel::Number::Channel1, peripherals.GPIO18),
ledc.channel(channel::Number::Channel2, peripherals.GPIO9),
ledc.channel(channel::Number::Channel3, peripherals.GPIO19),
ledc.channel(channel::Number::Channel4, peripherals.GPIO20),
ledc.channel(channel::Number::Channel5, peripherals.GPIO21),
]; ];
channels.iter_mut().for_each(|channel| { let mut pwm = SoftwarePWM::new();
channel let animations = [
.configure(channel::config::Config { wave_animation,
timer: &lstimer0, surge_animation,
duty_pct: 0, binary_animation,
pin_config: PinConfig::PushPull, ping_animation,
}) ];
.unwrap();
});
let delay = Delay::new();
let animations = [wave_animation, surge_animation, binary_animation, ping_animation, tyler_animation];
let mut current_animation_index = 0; let mut current_animation_index = 0;
let mut animation_start_time = 0u32;
let animation_switch_interval_ms = 3000; let animation_switch_interval_ms = 3000;
let frame_delay_ms = 10;
let mut animation_start = Instant::now();
loop { loop {
let current_animation = animations[current_animation_index]; 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();
});
delay.delay_millis(frame_delay_ms); let animation_elapsed_ms = animation_start.elapsed().as_millis() as u32;
animation_start_time += frame_delay_ms; let led_values = current_animation(animation_elapsed_ms);
if animation_start_time >= animation_switch_interval_ms { pwm.set_duty_cycles(led_values);
animation_start_time = 0;
let pwm_cycles = 100;
for _ in 0..pwm_cycles {
for i in 0..8 {
if pwm.should_be_high(i) {
leds[i].set_high();
} else {
leds[i].set_low();
}
}
pwm.update_step();
let delay_start = Instant::now();
while delay_start.elapsed() < Duration::from_micros(5) {}
}
if animation_elapsed_ms >= animation_switch_interval_ms {
animation_start = Instant::now();
current_animation_index = (current_animation_index + 1) % animations.len(); current_animation_index = (current_animation_index + 1) % animations.len();
info!("Switching to animation {}", current_animation_index);
} }
} }
} }