animation
This commit is contained in:
parent
b9363f1c7d
commit
8e96e70cfd
4 changed files with 125 additions and 24 deletions
2
Cargo.lock
generated
2
Cargo.lock
generated
|
|
@ -763,9 +763,11 @@ dependencies = [
|
||||||
"embedded-io",
|
"embedded-io",
|
||||||
"embedded-io-async",
|
"embedded-io-async",
|
||||||
"embedded-storage",
|
"embedded-storage",
|
||||||
|
"fixed",
|
||||||
"heapless",
|
"heapless",
|
||||||
"mipidsi",
|
"mipidsi",
|
||||||
"rgb",
|
"rgb",
|
||||||
|
"smart-leds",
|
||||||
"tinytga",
|
"tinytga",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -48,3 +48,5 @@ embassy-futures = "0.1.2"
|
||||||
heapless = "0.8.0"
|
heapless = "0.8.0"
|
||||||
rgb = "0.8.52"
|
rgb = "0.8.52"
|
||||||
tinytga = "0.5.0"
|
tinytga = "0.5.0"
|
||||||
|
smart-leds = "0.4.0"
|
||||||
|
fixed = "1.29.0"
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,7 @@
|
||||||
use embedded_graphics::{image::Image, pixelcolor::Rgb888, prelude::*};
|
use embassy_time::Duration;
|
||||||
|
use embedded_graphics::{image::Image, pixelcolor::Rgb888, prelude::*, primitives::Rectangle};
|
||||||
|
use fixed::types::U0F8;
|
||||||
|
use smart_leds::hsv::{Hsv, hsv2rgb};
|
||||||
use tinytga::Tga;
|
use tinytga::Tga;
|
||||||
|
|
||||||
pub struct Hal {
|
pub struct Hal {
|
||||||
|
|
@ -15,7 +18,6 @@ impl Hal {
|
||||||
|
|
||||||
impl Drawable for Hal {
|
impl Drawable for Hal {
|
||||||
type Color = Rgb888;
|
type Color = Rgb888;
|
||||||
|
|
||||||
type Output = ();
|
type Output = ();
|
||||||
|
|
||||||
fn draw<D>(&self, target: &mut D) -> Result<Self::Output, D::Error>
|
fn draw<D>(&self, target: &mut D) -> Result<Self::Output, D::Error>
|
||||||
|
|
@ -40,7 +42,6 @@ impl HappyEyes {
|
||||||
|
|
||||||
impl Drawable for HappyEyes {
|
impl Drawable for HappyEyes {
|
||||||
type Color = Rgb888;
|
type Color = Rgb888;
|
||||||
|
|
||||||
type Output = ();
|
type Output = ();
|
||||||
|
|
||||||
fn draw<D>(&self, target: &mut D) -> Result<Self::Output, D::Error>
|
fn draw<D>(&self, target: &mut D) -> Result<Self::Output, D::Error>
|
||||||
|
|
@ -50,3 +51,86 @@ impl Drawable for HappyEyes {
|
||||||
self.image_data.draw(target)
|
self.image_data.draw(target)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub struct Rainbow {
|
||||||
|
pub rate: Duration,
|
||||||
|
pub width: u32,
|
||||||
|
|
||||||
|
pub elapsed: Duration,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Rainbow {
|
||||||
|
fn map(&self, x: i32) -> Rgb888 {
|
||||||
|
let hue = ((x as f32 / self.width as f32
|
||||||
|
+ self.elapsed.as_micros() as f32 / self.rate.as_micros() as f32)
|
||||||
|
* 256.0) as u32 as u8;
|
||||||
|
let color = hsv2rgb(Hsv {
|
||||||
|
hue,
|
||||||
|
sat: 255,
|
||||||
|
val: 255,
|
||||||
|
});
|
||||||
|
Rgb888::new(color.r, color.g, color.b)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Drawable for Rainbow {
|
||||||
|
type Color = Rgb888;
|
||||||
|
type Output = ();
|
||||||
|
|
||||||
|
fn draw<D>(&self, target: &mut D) -> Result<Self::Output, D::Error>
|
||||||
|
where
|
||||||
|
D: DrawTarget<Color = Self::Color>,
|
||||||
|
{
|
||||||
|
let bb = target.bounding_box();
|
||||||
|
for dx in 0..bb.size.width {
|
||||||
|
let color = self.map(dx as i32);
|
||||||
|
target.fill_solid(
|
||||||
|
&Rectangle::new(
|
||||||
|
bb.top_left + Point::new(dx as i32, 0),
|
||||||
|
Size::new(1, bb.size.height),
|
||||||
|
),
|
||||||
|
color,
|
||||||
|
)?;
|
||||||
|
}
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub struct RainbowFilter<'a, D> {
|
||||||
|
pub inner_target: &'a mut D,
|
||||||
|
pub rainbow: &'a Rainbow,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'a, D: DrawTarget<Color = Rgb888>> DrawTarget for RainbowFilter<'a, D> {
|
||||||
|
type Color = D::Color;
|
||||||
|
type Error = D::Error;
|
||||||
|
|
||||||
|
fn draw_iter<I>(&mut self, pixels: I) -> Result<(), Self::Error>
|
||||||
|
where
|
||||||
|
I: IntoIterator<Item = Pixel<Self::Color>>,
|
||||||
|
{
|
||||||
|
self.inner_target.draw_iter(
|
||||||
|
pixels
|
||||||
|
.into_iter()
|
||||||
|
.map(|Pixel(point, color)| Pixel(point, mix(color, self.rainbow.map(point.x)))),
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'a, D: Dimensions> Dimensions for RainbowFilter<'a, D> {
|
||||||
|
fn bounding_box(&self) -> Rectangle {
|
||||||
|
self.inner_target.bounding_box()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn mix_u8(a: u8, b: u8) -> u8 {
|
||||||
|
(a as u16 * b as u16 / 255) as u8
|
||||||
|
}
|
||||||
|
|
||||||
|
fn mix(a: Rgb888, b: Rgb888) -> Rgb888 {
|
||||||
|
Rgb888::new(
|
||||||
|
mix_u8(a.r(), b.r()),
|
||||||
|
mix_u8(a.g(), b.g()),
|
||||||
|
mix_u8(a.b(), b.b()),
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -16,7 +16,7 @@ use embassy_rp::pio_programs::ws2812::{PioWs2812, PioWs2812Program};
|
||||||
use embassy_rp::pwm::{self, Pwm};
|
use embassy_rp::pwm::{self, Pwm};
|
||||||
use embassy_rp::rom_data::reset_to_usb_boot;
|
use embassy_rp::rom_data::reset_to_usb_boot;
|
||||||
use embassy_rp::spi::{self, Blocking, Spi};
|
use embassy_rp::spi::{self, Blocking, Spi};
|
||||||
use embassy_time::Delay;
|
use embassy_time::{Delay, Duration, Instant, Ticker};
|
||||||
use embedded_graphics::image::{Image, ImageRawLE};
|
use embedded_graphics::image::{Image, ImageRawLE};
|
||||||
use embedded_graphics::mono_font::MonoTextStyle;
|
use embedded_graphics::mono_font::MonoTextStyle;
|
||||||
use embedded_graphics::mono_font::ascii::FONT_10X20;
|
use embedded_graphics::mono_font::ascii::FONT_10X20;
|
||||||
|
|
@ -30,7 +30,7 @@ use mipidsi::interface::SpiInterface;
|
||||||
use mipidsi::models::ST7789;
|
use mipidsi::models::ST7789;
|
||||||
use mipidsi::options::Orientation;
|
use mipidsi::options::Orientation;
|
||||||
|
|
||||||
use crate::art::{Hal, HappyEyes};
|
use crate::art::{Hal, HappyEyes, Rainbow, RainbowFilter};
|
||||||
use crate::led_matrix::{LedMatrix, Serpentine};
|
use crate::led_matrix::{LedMatrix, Serpentine};
|
||||||
|
|
||||||
use defmt_rtt as _;
|
use defmt_rtt as _;
|
||||||
|
|
@ -116,8 +116,7 @@ async fn main(spawner: Spawner) -> ! {
|
||||||
|
|
||||||
let mut led_pio = Pio::new(p.PIO0, Irqs);
|
let mut led_pio = Pio::new(p.PIO0, Irqs);
|
||||||
let led_program = PioWs2812Program::new(&mut led_pio.common);
|
let led_program = PioWs2812Program::new(&mut led_pio.common);
|
||||||
|
let led_surface = LedMatrix::new(
|
||||||
let mut led_surface = LedMatrix::new(
|
|
||||||
Serpentine {
|
Serpentine {
|
||||||
size: Size::new(40, 8),
|
size: Size::new(40, 8),
|
||||||
},
|
},
|
||||||
|
|
@ -129,23 +128,7 @@ async fn main(spawner: Spawner) -> ! {
|
||||||
&led_program,
|
&led_program,
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
led_surface.clear(Rgb888::BLACK).ok();
|
spawner.spawn(led_task(led_surface)).ok();
|
||||||
/*
|
|
||||||
Rectangle::new(Point::zero(), led_surface.size())
|
|
||||||
.into_styled(
|
|
||||||
PrimitiveStyleBuilder::new()
|
|
||||||
.stroke_color(Rgb888::RED)
|
|
||||||
.stroke_width(1)
|
|
||||||
.fill_color(Rgb888::CSS_DARK_BLUE)
|
|
||||||
.build(),
|
|
||||||
)
|
|
||||||
.draw(&mut led_surface)
|
|
||||||
.ok();
|
|
||||||
*/
|
|
||||||
// let hal = Hal::new();
|
|
||||||
let eyes = HappyEyes::new();
|
|
||||||
eyes.draw(&mut led_surface).ok();
|
|
||||||
led_surface.sync().await;
|
|
||||||
|
|
||||||
let mut render = |f_keys: [bool; 4]| {
|
let mut render = |f_keys: [bool; 4]| {
|
||||||
display.clear(Rgb565::BLACK).ok();
|
display.clear(Rgb565::BLACK).ok();
|
||||||
|
|
@ -186,6 +169,36 @@ async fn main(spawner: Spawner) -> ! {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[embassy_executor::task]
|
||||||
|
async fn led_task(mut led_surface: LedMatrix<'static>) {
|
||||||
|
let hal = Hal::new();
|
||||||
|
let eyes = HappyEyes::new();
|
||||||
|
let mut rainbow = Rainbow {
|
||||||
|
// rate: Duration::from_secs(10),
|
||||||
|
// width: 300,
|
||||||
|
rate: Duration::from_secs(1),
|
||||||
|
width: 80,
|
||||||
|
elapsed: Duration::from_secs(0),
|
||||||
|
};
|
||||||
|
|
||||||
|
let mut ticker = Ticker::every(Duration::from_hz(30));
|
||||||
|
let start = Instant::now();
|
||||||
|
|
||||||
|
loop {
|
||||||
|
let elapsed = start.elapsed();
|
||||||
|
rainbow.elapsed = elapsed;
|
||||||
|
|
||||||
|
led_surface.clear(Rgb888::BLACK).ok();
|
||||||
|
eyes.draw(&mut RainbowFilter {
|
||||||
|
inner_target: &mut led_surface,
|
||||||
|
rainbow: &rainbow,
|
||||||
|
})
|
||||||
|
.ok();
|
||||||
|
led_surface.sync().await;
|
||||||
|
ticker.next().await;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#[embassy_executor::task]
|
#[embassy_executor::task]
|
||||||
async fn dfu_button(mut btn_y: Input<'static>) {
|
async fn dfu_button(mut btn_y: Input<'static>) {
|
||||||
btn_y.wait_for_falling_edge().await;
|
btn_y.wait_for_falling_edge().await;
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue