use figments::{hardware::{Brightness, Gamma, OutputAsync}, mappings::linear::LinearSpace, power::AsMilliwatts, prelude::*, smart_leds::{BrightnessWriter, BrightnessWriterAsync}}; use core::{fmt::Debug, ops::IndexMut}; //use std::io::Write; //use super::{Output}; use figments::hardware::Output; use smart_leds::{SmartLedsWrite, SmartLedsWriteAsync}; pub trait LinearPixbuf: Pixbuf + Sample<'static, LinearSpace, Output = Self::Format> + IndexMut + AsRef<[Self::Format]> {} impl LinearPixbuf for T where T: Pixbuf + Sample<'static, LinearSpace, Output = Self::Format> + IndexMut + AsRef<[Self::Format]> {} pub struct BikeOutput { pixbuf: [T::Color; 178], writer: BrightnessWriter } impl Debug for BikeOutput { fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result { f.debug_struct("BikeOutput").field("pixbuf", &core::any::type_name_of_val(&self.pixbuf)).field("writer", &core::any::type_name_of_val(&self.writer)).finish() } } impl BikeOutput where T::Color: HardwarePixel + Gamma + Fract8Ops, T::Error: core::fmt::Debug { pub fn new(target: T, max_mw: u32) -> Self { Self { pixbuf: [Default::default(); 178], writer: BrightnessWriter::new(target, max_mw) } } } impl Brightness for BikeOutput where T::Color: HardwarePixel + Gamma + Fract8Ops, T::Error: core::fmt::Debug { fn set_brightness(&mut self, brightness: u8) { self.writer.set_brightness(brightness); } fn set_on(&mut self, is_on: bool) { self.writer.set_on(is_on); } fn set_gamma(&mut self, gamma: f32) { self.writer.set_gamma(gamma); } } impl<'a, T: SmartLedsWrite + 'a> Output<'a, BikeSpace> for BikeOutput where T::Color: 'static + HardwarePixel + Gamma + Fract8Ops, [T::Color; 178]: AsMilliwatts + Gamma + Copy, T::Error: core::fmt::Debug { fn blank(&mut self) -> Result<(), Self::Error> { self.pixbuf.blank(); Ok(()) } fn commit(&mut self) -> Result<(), Self::Error> { self.writer.write(&self.pixbuf) } type HardwarePixel = T::Color; type Error = T::Error; } impl<'a, T: SmartLedsWrite> Sample<'a, BikeSpace> for BikeOutput where T::Color: HardwarePixel + Gamma + Fract8Ops, [T::Color; 178]: AsMilliwatts + 'static { type Output = T::Color; fn sample(&mut self, rect: &Rectangle) -> impl Iterator, &'a mut Self::Output)> { let bufref = unsafe { &mut *(&mut self.pixbuf as *mut [T::Color; 178]) }; BikeIter { pixbuf: bufref, cur: rect.top_left, end: rect.bottom_right } } } // ASYNC pub struct BikeOutputAsync { pixbuf: [T::Color; 178], writer: BrightnessWriterAsync } impl Debug for BikeOutputAsync { fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result { f.debug_struct("BikeOutput").field("pixbuf", &core::any::type_name_of_val(&self.pixbuf)).field("writer", &core::any::type_name_of_val(&self.writer)).finish() } } impl BikeOutputAsync where T::Color: HardwarePixel + Gamma + Fract8Ops, T::Error: core::fmt::Debug { pub fn new(target: T, max_mw: u32) -> Self { Self { pixbuf: [Default::default(); 178], writer: BrightnessWriterAsync::new(target, max_mw) } } } impl Brightness for BikeOutputAsync where T::Color: HardwarePixel + Gamma + Fract8Ops, T::Error: core::fmt::Debug { fn set_brightness(&mut self, brightness: u8) { self.writer.set_brightness(brightness); } fn set_on(&mut self, is_on: bool) { self.writer.set_on(is_on); } fn set_gamma(&mut self, gamma: f32) { self.writer.set_gamma(gamma); } } impl<'a, T: SmartLedsWriteAsync + 'a> OutputAsync<'a, BikeSpace> for BikeOutputAsync where T::Color: 'static + HardwarePixel + Gamma + Fract8Ops, [T::Color; 178]: AsMilliwatts + Gamma + Copy, T::Error: core::fmt::Debug { async fn blank_async(&mut self) -> Result<(), Self::Error> { self.pixbuf.blank(); Ok(()) } async fn commit_async(&mut self) -> Result<(), Self::Error> { self.writer.write(&self.pixbuf).await } type HardwarePixel = T::Color; type Error = T::Error; } impl<'a, T: SmartLedsWriteAsync> Sample<'a, BikeSpace> for BikeOutputAsync where T::Color: HardwarePixel + Gamma + Fract8Ops, [T::Color; 178]: AsMilliwatts + 'static { type Output = T::Color; fn sample(&mut self, rect: &Rectangle) -> impl Iterator, &'a mut Self::Output)> { let bufref = unsafe { &mut *(&mut self.pixbuf as *mut [T::Color; 178]) }; BikeIter { pixbuf: bufref, cur: rect.top_left, end: rect.bottom_right } } } struct Strip { start: usize, length: usize, } const STRIP_MAP: [Strip; 6] = [ Strip { start: 0, length: 28 }, Strip { start: 28, length: 17 }, Strip { start: 45, length: 14 }, Strip { start: 59, length: 17 }, Strip { start: 76, length: 14 }, Strip { start: 90, length: 88 } ]; #[derive(Clone, Copy, Default, Debug)] pub struct BikeSpace {} impl CoordinateSpace for BikeSpace { type Data = usize; } pub struct BikeIter<'a, P: LinearPixbuf + Debug> { pixbuf: &'a mut P, cur: Coordinates, end: Coordinates } impl<'a, P: LinearPixbuf + Debug> Debug for BikeIter<'a, P> { fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result { f.debug_struct("BikeIter").field("cur", &self.cur).field("end", &self.end).finish() } } impl<'a, P: LinearPixbuf + Debug> Iterator for BikeIter<'a, P> { type Item = (Coordinates, &'a mut P::Format); fn next(&mut self) -> Option { if self.cur.y > self.end.y || self.cur.y >= STRIP_MAP.len() { return None; } let this_strip = &STRIP_MAP[self.cur.y]; let offset = this_strip.start + self.cur.x; let pixel_coords = Coordinates::new(self.cur.x, self.cur.y); self.cur.x += 1; if self.cur.x >= this_strip.length || self.cur.x > self.end.x { self.cur.x = 0; self.cur.y += 1; } let bufref = unsafe { &mut *(self.pixbuf as *mut P) }; Some((pixel_coords, &mut bufref[offset])) } }