src: rewrite display to have generic surface implementations

This commit is contained in:
2024-10-28 22:22:03 +01:00
parent ed034046e8
commit e475d66842
4 changed files with 146 additions and 78 deletions

View File

@@ -3,23 +3,40 @@ use embedded_graphics::{
pixelcolor::Rgb888,
primitives::Rectangle
};
use embedded_graphics::pixelcolor::RgbColor;
use ws2812_esp32_rmt_driver::lib_embedded_graphics::{Ws2812DrawTarget, LedPixelShape};
use std::rc::Rc;
use std::cell::RefCell;
use std::sync::{Arc, Mutex};
use running_average::RealTimeRunningAverage;
use std::io;
use crate::power;
use crate::power::AsMilliwatts;
use crate::lib8::*;
use crate::render::*;
use crate::time::Periodically;
use crate::task::Task;
use crate::geometry::*;
pub struct EmbeddedDisplay<T>
impl<T: RgbColor> AsMilliwatts for T {
fn as_milliwatts(&self) -> u32 {
const RED_MW : u32 = 16 * 5; //< 16mA @ 5v = 80mW
const GREEN_MW : u32 = 11 * 5; //< 11mA @ 5v = 55mW
const BLUE_MW : u32 = 15 * 5; //< 15mA @ 5v = 75mW
const DARK_MW : u32 = 1 * 5; //< 1mA @ 5v = 5mW
let red = (self.r() as u32 * RED_MW).wrapping_shr(8);
let green = (self.g() as u32 * GREEN_MW).wrapping_shr(8);
let blue = (self.b() as u32 * BLUE_MW).wrapping_shr(8);
return red + green + blue + DARK_MW;
}
}
pub struct EmbeddedDisplay<T, S>
where
T: DrawTarget {
surfaces : RefCell<Vec<Surface>>,
T: DrawTarget,
S: Surface + Default + Clone {
surfaces : SurfacePool<S>,
target: T,
total_mw: u32,
max_mw: u32,
@@ -28,12 +45,27 @@ T: DrawTarget {
fps_display: Periodically
}
impl<T> EmbeddedDisplay<T>
impl<T: LedPixelShape, S: Surface + Default + Clone> Task for EmbeddedDisplay<Ws2812DrawTarget<'_, T>, S> {
fn start(&mut self) {
self.target.set_brightness(0);
}
fn name(&self) -> &'static str { "Renderer" }
fn tick(&mut self) {
self.start_frame();
self.render_frame();
self.end_frame();
}
}
impl<T, S> EmbeddedDisplay<T, S>
where
T: DrawTarget {
T: DrawTarget,
S: Surface + Default + Clone {
pub fn new(target: T, max_mw: u32) -> Self {
EmbeddedDisplay {
surfaces: RefCell::new(Vec::new()),
surfaces: SurfacePool::new(),
target: target,
max_mw: max_mw,
total_mw: 0,
@@ -44,17 +76,17 @@ T: DrawTarget {
}
}
impl<T> Surfaces for EmbeddedDisplay<T>
impl<T, S> Surfaces<S> for EmbeddedDisplay<T, S>
where
T: DrawTarget {
fn new_surface(&mut self) -> Surface {
let surface = Surface::new();
self.surfaces.borrow_mut().push(surface.clone());
return surface;
T: DrawTarget,
S: Surface + Default + Clone {
fn new_surface(&mut self) -> Result<S, io::Error> {
self.surfaces.new_surface()
}
}
impl<T: LedPixelShape> Display for EmbeddedDisplay<Ws2812DrawTarget<'_, T>> {
impl<T: LedPixelShape, S: Surface + Default + Clone> Display<S> for EmbeddedDisplay<Ws2812DrawTarget<'_, T>, S> {
fn start_frame(&mut self) {
self.total_mw = 0;
self.frame = self.frame.wrapping_add(1);
@@ -76,19 +108,17 @@ impl<T: LedPixelShape> Display for EmbeddedDisplay<Ws2812DrawTarget<'_, T>> {
let yStride: u8 = 255 / (size.height as u8);
let area = Rectangle::new(Point::new(0, 0), size);
let surfaces = self.surfaces.borrow();
self.target.draw_iter(
area.points()
.map(|pos| {
let virtCoords = VirtualCoordinates::new(pos.x as u8 * xStride, pos.y as u8 * yStride);
let mut pixel = RGB8::new(0, 0, 0);
for surface in surfaces.iter() {
for surface in self.surfaces.iter() {
surface.with_shader(|shader| {
pixel = shader.draw(virtCoords.clone());
})
}
self.total_mw += power::color_to_mw(&pixel);
self.total_mw += pixel.as_milliwatts();
return Pixel(pos, Rgb888::new(pixel.red, pixel.green, pixel.blue));
})
).unwrap();