use embedded_graphics::{ prelude::*, pixelcolor::Rgb888, primitives::Rectangle }; 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 crate::power; use crate::lib8::*; use crate::render::*; use crate::time::Periodically; use crate::geometry::*; pub struct EmbeddedDisplay where T: DrawTarget { surfaces : RefCell>, target: T, total_mw: u32, max_mw: u32, fps: RealTimeRunningAverage, frame: u32, fps_display: Periodically } impl EmbeddedDisplay where T: DrawTarget { pub fn new(target: T, max_mw: u32) -> Self { EmbeddedDisplay { surfaces: RefCell::new(Vec::new()), target: target, max_mw: max_mw, total_mw: 0, fps: RealTimeRunningAverage::default(), frame: 0, fps_display: Periodically::new_every_n_seconds(5) } } } impl Surfaces for EmbeddedDisplay where T: DrawTarget { fn new_surface(&mut self) -> Surface { let surface = Surface::new(); self.surfaces.borrow_mut().push(surface.clone()); return surface; } } impl Display for EmbeddedDisplay> { fn start_frame(&mut self) { self.total_mw = 0; self.frame = self.frame.wrapping_add(1); } fn end_frame(&mut self) { let brightness = power::brightness_for_mw(self.total_mw, 255, self.max_mw); self.target.set_brightness(brightness); self.target.flush().unwrap(); self.fps.insert(1); self.fps_display.run(|| { log::info!("FPS: {} frame={} brightness={} mw={}", self.fps.measurement(), self.frame, brightness, self.total_mw); }); } fn render_frame(&mut self) { let size = T::size(); let xStride: u8 = 255 / (size.width as u8); 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() { surface.with_shader(|shader| { pixel = shader.draw(virtCoords.clone()); }) } self.total_mw += power::color_to_mw(&pixel); return Pixel(pos, Rgb888::new(pixel.red, pixel.green, pixel.blue)); }) ).unwrap(); } }