renderbug: first implementation of surface-based rendering

This commit is contained in:
2024-10-27 11:19:26 +01:00
parent ea5232e048
commit 4432ba7ad0
6 changed files with 380 additions and 44 deletions

View File

@@ -1,17 +1,58 @@
#![feature(trait_upcasting)]
#![allow(arithmetic_overflow)]
use esp_idf_svc::hal::prelude::Peripherals;
use ws2812_esp32_rmt_driver::lib_embedded_graphics::{LedPixelStrip, Ws2812DrawTarget};
use embedded_graphics::{
prelude::*,
pixelcolor::Rgb888,
};
use palette::Hsv;
use palette::convert::IntoColorUnclamped;
use std::thread;
mod power;
mod lib8;
mod render;
mod task;
mod time;
use crate::time::Periodically;
struct IdleTask {
frame: u8,
surface: render::Surface,
updater: Periodically
}
struct IdleShader {
frame: u8
}
impl render::Shader for IdleShader {
fn draw(&self, coords: Point) -> lib8::RGB8 {
Hsv::new_srgb(self.frame.wrapping_add(coords.x as u8), 255, 255).into_color_unclamped()
}
}
impl IdleTask {
fn new(render: &mut dyn render::Display) -> Self {
IdleTask {
frame: 0,
surface: render.new_surface(),
updater: Periodically::new_every_n_ms(16)
}
}
}
impl task::Task for IdleTask {
fn name(&self) -> &'static str { "Idle" }
fn tick(&mut self) {
self.updater.run(|| {
self.frame = self.frame.wrapping_add(1);
self.surface.set_shader(Box::new(IdleShader { frame: self.frame }));
})
}
}
fn main() {
// It is necessary to call this function once. Otherwise some patches to the runtime
@@ -32,35 +73,18 @@ fn main() {
const POWER_MA : u32 = 500;
const MAX_POWER_MW : u32 = POWER_VOLTS * POWER_MA;
let mut draw = Ws2812DrawTarget::<LedPixelStrip<NUM_PIXELS>>::new(channel, led_pin).unwrap();
let mut hue : u8 = 0;
let mut length : usize = NUM_PIXELS;
let mut forwards = false;
loop {
let mut totalMW = 0;
draw.clear(Rgb888::BLACK);
for i in 0..length {
let hsvColor = Hsv::new_srgb(hue.wrapping_add(i as u8), 255, 255);
let rgbColor : lib8::RGB8 = hsvColor.into_color_unclamped();
let color = Rgb888::new(rgbColor.red, rgbColor.green, rgbColor.blue);
log::info!("Setting up display");
let target = Ws2812DrawTarget::<LedPixelStrip<NUM_PIXELS>>::new(channel, led_pin).unwrap();
let mut display = render::EmbeddedDisplay::new(target, MAX_POWER_MW);
totalMW += power::colorToMW(color);
Pixel(Point::new(i as i32, 0), color).draw(&mut draw).unwrap();
}
let brightness = power::brightnessForMW(totalMW, 255, MAX_POWER_MW);
draw.set_brightness(brightness);
draw.flush().unwrap();
log::info!("Frame hue={} power={} brightness={}", hue, totalMW, brightness);
hue = hue.wrapping_add(1);
if forwards {
length += 1
} else {
length -= 1
}
if length <= 1 {
forwards = true;
} else if length >= NUM_PIXELS {
forwards = false;
}
log::info!("Creating runner");
let mut runner = task::Scheduler::new(vec![
Box::new(IdleTask::new(&mut display)),
Box::new(display),
]);
log::info!("Ready to rock and roll");
loop {
runner.tick();
}
}