diff --git a/Cargo.lock b/Cargo.lock index 3f06027..d3bf475 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -900,6 +900,7 @@ dependencies = [ "esp-println", "esp-wifi", "heapless", + "libm", "log", "smart-leds", "smoltcp", diff --git a/Cargo.toml b/Cargo.toml index f5b1b41..ef58a31 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -66,6 +66,7 @@ smart-leds = "0.4.0" ws2812-spi = "0.5.0" embassy-futures = "0.1.1" embassy-sync = "0.7.0" +libm = "0.2.15" [profile.dev] # Rust debug is too slow. diff --git a/src/bin/main.rs b/src/bin/main.rs index 66fe8cf..f512d9f 100644 --- a/src/bin/main.rs +++ b/src/bin/main.rs @@ -1,20 +1,28 @@ #![no_std] #![no_main] +use alloc::boxed::Box; +use core::ops::BitXor; +use core::ops::Rem; use core::pin::Pin; - use embassy_executor::Spawner; use embassy_futures::select::{Either, select}; +use embassy_sync::blocking_mutex::raw::CriticalSectionRawMutex; use embassy_sync::blocking_mutex::raw::NoopRawMutex; use embassy_sync::channel::{Channel, Sender}; +use embassy_sync::mutex::Mutex; +use embassy_sync::watch::{self, Watch}; use embassy_time::{Duration, Instant, Timer, WithTimeout}; use esp_hal::clock::CpuClock; -use esp_hal::gpio::{Input, InputConfig, Pull}; +use esp_hal::gpio::{DriveMode, Input, InputConfig, Pull}; use esp_hal::peripherals::GPIO; +use esp_hal::rng; use esp_hal::spi::master::{Config, Spi}; use esp_hal::time::Rate; use esp_hal::timer::systimer::SystemTimer; use esp_hal::timer::timg::TimerGroup; +use esp_hal::{Async, Blocking, DriverMode}; +use libm::sin; use log::info; use smart_leds::RGB8; use smart_leds::SmartLedsWrite; @@ -28,11 +36,30 @@ fn panic(_: &core::panic::PanicInfo) -> ! { extern crate alloc; +#[derive(Clone, Debug, PartialEq, Eq)] +struct TargetState { + enabled: [bool; 12], +} + +impl Default for TargetState { + fn default() -> Self { + TargetState { + enabled: [false; 12], + } + } +} + static CHANNEL: StaticCell> = StaticCell::new(); +static STATE: Mutex = Mutex::new(TargetState { + enabled: [false; 12], +}); + +const ORDER: [usize; 12] = [5, 6, 4, 7, 3, 8, 2, 9, 1, 10, 0, 11]; #[esp_hal_embassy::main] async fn main(spawner: Spawner) { let channel = CHANNEL.init(Channel::new()); + //let state_watch = STATE.init(Arc::new(Mutex::new(TargetState::default()))); // generator version: 0.3.1 esp_println::logger::init_logger_from_env(); @@ -55,23 +82,7 @@ async fn main(spawner: Spawner) { ) .unwrap(); - spawner - .spawn(listen_rotary_encoder( - RotaryEncoderConfig { - clk: Input::new( - peripherals.GPIO8, - InputConfig::default().with_pull(Pull::Up), - ), - ot: Input::new( - peripherals.GPIO10, - InputConfig::default().with_pull(Pull::Up), - ), - }, - channel.sender(), - )) - .unwrap(); - - let mut led_strip = { + let led_strip = { let spi = Spi::new( peripherals.SPI2, Config::default().with_frequency(Rate::from_mhz(3)), @@ -81,56 +92,35 @@ async fn main(spawner: Spawner) { Ws2812::new(spi) }; - let colors = [ - RGB8 { r: 0, g: 255, b: 0 }, - RGB8 { r: 255, g: 0, b: 0 }, - RGB8 { r: 255, g: 0, b: 0 }, - RGB8 { - r: 0, - g: 255, - b: 255, - }, - RGB8 { - r: 255, - g: 0, - b: 255, - }, - RGB8 { - r: 255, - g: 255, - b: 0, - }, - ]; - let mut color_idx = 0; + let encoder = RotaryEncoderConfig { + clk: Input::new( + peripherals.GPIO8, + InputConfig::default().with_pull(Pull::Up), + ), + ot: Input::new( + peripherals.GPIO10, + InputConfig::default().with_pull(Pull::Up), + ), + }; + spawner + .spawn(listen_rotary_encoder(encoder, channel.sender())) + .unwrap(); + spawner.spawn(render_gems(led_strip)).unwrap(); + let mut state = TargetState::default(); + let mut cnt = 0; loop { let delta = channel.receive().await; - color_idx += delta; - // led_strip - // .write([ - // colors[color_idx % colors.len()], - // colors[(color_idx + 1) % colors.len()], - // colors[(color_idx + 2) % colors.len()], - // colors[(color_idx + 3) % colors.len()], - // ]) - // .unwrap(); - // + cnt = (cnt + delta).clamp(0, 12); - let cnt = 12; - - led_strip - .write((0..cnt).map(|it| { - if it <= (color_idx % cnt) { - RGB8 { - r: 255, - g: 50, - b: 00, - } - } else { - RGB8 { r: 0, g: 0, b: 0 } - } - })) - .unwrap(); + state.enabled = [false; 12]; + for i in (0..12) { + state.enabled[ORDER[i]] = (cnt > i as i32); + } + { + let mut state_lock = STATE.lock().await; + *state_lock = state.clone(); + } } // for inspiration have a look at the examples at https://github.com/esp-rs/esp-hal/tree/esp-hal-v1.0.0-beta.0/examples/src/bin @@ -153,6 +143,73 @@ enum RotaryDirection { Ccw, } +#[embassy_executor::task] +async fn render_gems( + mut strip: Ws2812>, + //target: Mutex, +) { + let mut temp = [0.0f32; 12]; + let mut last_state = TargetState::default(); + let mut frame = 0usize; + + loop { + frame = frame.wrapping_add(1); + + { + let target = STATE.lock().await; + + for i in (0..12) { + if target.enabled[i] && !last_state.enabled[i] { + temp[i] = 3.0; + } else { + let trg = if target.enabled[i] { 1.0 } else { 0.0 }; + let speed = ((temp[i] - trg).abs() * 0.2).clamp(0.1, 0.5); + + if temp[i] < trg { + temp[i] = (temp[i] + speed).min(trg); + } else { + temp[i] = (temp[i] - speed).max(trg); + } + } + } + + last_state = target.clone(); + } + + strip + .write(temp.iter().enumerate().map(|(index, it)| { + let temp = *it; + // let temp = *it + // + (((sin( + // //(index.wrapping_mul(182945).bitxor(48194291).rem(100) as f64) + + // (frame as f64 * 0.05), + // ) as f32) + // / 2.0 + // + 0.5) + // * 0.1); + + let green_tint = 20.0; + + if temp > 1.0 { + RGB8 { + r: 255u8, + g: (50.0 + (255.0 - 50.0) * (temp - 1.0)) as u8, + b: (255.0 * (temp - 1.0)) as u8, + } + } else { + RGB8 { + r: (255.0 * temp) as u8, + g: (green_tint * temp) as u8, + b: (20.0 * (1.0 - temp)) as u8, + } + } + })) + .unwrap(); + + Timer::after_millis(1000 / 24).await; + } +} + #[embassy_executor::task] async fn listen_rotary_encoder( mut config: RotaryEncoderConfig<'static, 'static>,