src: rewrite display to have generic surface implementations
This commit is contained in:
@@ -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();
|
||||
|
Reference in New Issue
Block a user