Improve visuals and animation
This commit is contained in:
parent
654bd8bdf6
commit
700bc71bf6
3 changed files with 124 additions and 65 deletions
1
Cargo.lock
generated
1
Cargo.lock
generated
|
|
@ -900,6 +900,7 @@ dependencies = [
|
||||||
"esp-println",
|
"esp-println",
|
||||||
"esp-wifi",
|
"esp-wifi",
|
||||||
"heapless",
|
"heapless",
|
||||||
|
"libm",
|
||||||
"log",
|
"log",
|
||||||
"smart-leds",
|
"smart-leds",
|
||||||
"smoltcp",
|
"smoltcp",
|
||||||
|
|
|
||||||
|
|
@ -66,6 +66,7 @@ smart-leds = "0.4.0"
|
||||||
ws2812-spi = "0.5.0"
|
ws2812-spi = "0.5.0"
|
||||||
embassy-futures = "0.1.1"
|
embassy-futures = "0.1.1"
|
||||||
embassy-sync = "0.7.0"
|
embassy-sync = "0.7.0"
|
||||||
|
libm = "0.2.15"
|
||||||
|
|
||||||
[profile.dev]
|
[profile.dev]
|
||||||
# Rust debug is too slow.
|
# Rust debug is too slow.
|
||||||
|
|
|
||||||
187
src/bin/main.rs
187
src/bin/main.rs
|
|
@ -1,20 +1,28 @@
|
||||||
#![no_std]
|
#![no_std]
|
||||||
#![no_main]
|
#![no_main]
|
||||||
|
|
||||||
|
use alloc::boxed::Box;
|
||||||
|
use core::ops::BitXor;
|
||||||
|
use core::ops::Rem;
|
||||||
use core::pin::Pin;
|
use core::pin::Pin;
|
||||||
|
|
||||||
use embassy_executor::Spawner;
|
use embassy_executor::Spawner;
|
||||||
use embassy_futures::select::{Either, select};
|
use embassy_futures::select::{Either, select};
|
||||||
|
use embassy_sync::blocking_mutex::raw::CriticalSectionRawMutex;
|
||||||
use embassy_sync::blocking_mutex::raw::NoopRawMutex;
|
use embassy_sync::blocking_mutex::raw::NoopRawMutex;
|
||||||
use embassy_sync::channel::{Channel, Sender};
|
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 embassy_time::{Duration, Instant, Timer, WithTimeout};
|
||||||
use esp_hal::clock::CpuClock;
|
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::peripherals::GPIO;
|
||||||
|
use esp_hal::rng;
|
||||||
use esp_hal::spi::master::{Config, Spi};
|
use esp_hal::spi::master::{Config, Spi};
|
||||||
use esp_hal::time::Rate;
|
use esp_hal::time::Rate;
|
||||||
use esp_hal::timer::systimer::SystemTimer;
|
use esp_hal::timer::systimer::SystemTimer;
|
||||||
use esp_hal::timer::timg::TimerGroup;
|
use esp_hal::timer::timg::TimerGroup;
|
||||||
|
use esp_hal::{Async, Blocking, DriverMode};
|
||||||
|
use libm::sin;
|
||||||
use log::info;
|
use log::info;
|
||||||
use smart_leds::RGB8;
|
use smart_leds::RGB8;
|
||||||
use smart_leds::SmartLedsWrite;
|
use smart_leds::SmartLedsWrite;
|
||||||
|
|
@ -28,11 +36,30 @@ fn panic(_: &core::panic::PanicInfo) -> ! {
|
||||||
|
|
||||||
extern crate alloc;
|
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<Channel<NoopRawMutex, i32, 2>> = StaticCell::new();
|
static CHANNEL: StaticCell<Channel<NoopRawMutex, i32, 2>> = StaticCell::new();
|
||||||
|
static STATE: Mutex<CriticalSectionRawMutex, TargetState> = 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]
|
#[esp_hal_embassy::main]
|
||||||
async fn main(spawner: Spawner) {
|
async fn main(spawner: Spawner) {
|
||||||
let channel = CHANNEL.init(Channel::new());
|
let channel = CHANNEL.init(Channel::new());
|
||||||
|
//let state_watch = STATE.init(Arc::new(Mutex::new(TargetState::default())));
|
||||||
// generator version: 0.3.1
|
// generator version: 0.3.1
|
||||||
|
|
||||||
esp_println::logger::init_logger_from_env();
|
esp_println::logger::init_logger_from_env();
|
||||||
|
|
@ -55,23 +82,7 @@ async fn main(spawner: Spawner) {
|
||||||
)
|
)
|
||||||
.unwrap();
|
.unwrap();
|
||||||
|
|
||||||
spawner
|
let led_strip = {
|
||||||
.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 spi = Spi::new(
|
let spi = Spi::new(
|
||||||
peripherals.SPI2,
|
peripherals.SPI2,
|
||||||
Config::default().with_frequency(Rate::from_mhz(3)),
|
Config::default().with_frequency(Rate::from_mhz(3)),
|
||||||
|
|
@ -81,56 +92,35 @@ async fn main(spawner: Spawner) {
|
||||||
Ws2812::new(spi)
|
Ws2812::new(spi)
|
||||||
};
|
};
|
||||||
|
|
||||||
let colors = [
|
let encoder = RotaryEncoderConfig {
|
||||||
RGB8 { r: 0, g: 255, b: 0 },
|
clk: Input::new(
|
||||||
RGB8 { r: 255, g: 0, b: 0 },
|
peripherals.GPIO8,
|
||||||
RGB8 { r: 255, g: 0, b: 0 },
|
InputConfig::default().with_pull(Pull::Up),
|
||||||
RGB8 {
|
),
|
||||||
r: 0,
|
ot: Input::new(
|
||||||
g: 255,
|
peripherals.GPIO10,
|
||||||
b: 255,
|
InputConfig::default().with_pull(Pull::Up),
|
||||||
},
|
),
|
||||||
RGB8 {
|
};
|
||||||
r: 255,
|
spawner
|
||||||
g: 0,
|
.spawn(listen_rotary_encoder(encoder, channel.sender()))
|
||||||
b: 255,
|
.unwrap();
|
||||||
},
|
spawner.spawn(render_gems(led_strip)).unwrap();
|
||||||
RGB8 {
|
|
||||||
r: 255,
|
|
||||||
g: 255,
|
|
||||||
b: 0,
|
|
||||||
},
|
|
||||||
];
|
|
||||||
let mut color_idx = 0;
|
|
||||||
|
|
||||||
|
let mut state = TargetState::default();
|
||||||
|
let mut cnt = 0;
|
||||||
loop {
|
loop {
|
||||||
let delta = channel.receive().await;
|
let delta = channel.receive().await;
|
||||||
color_idx += delta;
|
cnt = (cnt + delta).clamp(0, 12);
|
||||||
// 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();
|
|
||||||
//
|
|
||||||
|
|
||||||
let cnt = 12;
|
state.enabled = [false; 12];
|
||||||
|
for i in (0..12) {
|
||||||
led_strip
|
state.enabled[ORDER[i]] = (cnt > i as i32);
|
||||||
.write((0..cnt).map(|it| {
|
}
|
||||||
if it <= (color_idx % cnt) {
|
{
|
||||||
RGB8 {
|
let mut state_lock = STATE.lock().await;
|
||||||
r: 255,
|
*state_lock = state.clone();
|
||||||
g: 50,
|
}
|
||||||
b: 00,
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
RGB8 { r: 0, g: 0, b: 0 }
|
|
||||||
}
|
|
||||||
}))
|
|
||||||
.unwrap();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// 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
|
// 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,
|
Ccw,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[embassy_executor::task]
|
||||||
|
async fn render_gems(
|
||||||
|
mut strip: Ws2812<Spi<'static, Blocking>>,
|
||||||
|
//target: Mutex<NoopRawMutex, TargetState>,
|
||||||
|
) {
|
||||||
|
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]
|
#[embassy_executor::task]
|
||||||
async fn listen_rotary_encoder(
|
async fn listen_rotary_encoder(
|
||||||
mut config: RotaryEncoderConfig<'static, 'static>,
|
mut config: RotaryEncoderConfig<'static, 'static>,
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue