Files
renderbug-bike/src/display.rs

198 lines
6.5 KiB
Rust

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<usize, Output = Self::Format> + AsRef<[Self::Format]> {}
impl<T> LinearPixbuf for T where T: Pixbuf + Sample<'static, LinearSpace, Output = Self::Format> + IndexMut<usize, Output = Self::Format> + AsRef<[Self::Format]> {}
pub struct BikeOutput<T: SmartLedsWrite> {
pixbuf: [T::Color; 178],
writer: BrightnessWriter<T>
}
impl<T: SmartLedsWrite> Debug for BikeOutput<T> {
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<T: SmartLedsWrite> BikeOutput<T> 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<T: SmartLedsWrite> Brightness for BikeOutput<T> 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<T> 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<T> where T::Color: HardwarePixel + Gamma + Fract8Ops, [T::Color; 178]: AsMilliwatts + 'static {
type Output = T::Color;
fn sample(&mut self, rect: &Rectangle<BikeSpace>) -> impl Iterator<Item = (Coordinates<BikeSpace>, &'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<T: SmartLedsWriteAsync> {
pixbuf: [T::Color; 178],
writer: BrightnessWriterAsync<T>
}
impl<T: SmartLedsWriteAsync> Debug for BikeOutputAsync<T> {
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<T: SmartLedsWriteAsync> BikeOutputAsync<T> 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<T: SmartLedsWriteAsync> Brightness for BikeOutputAsync<T> 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<T> 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<T> where T::Color: HardwarePixel + Gamma + Fract8Ops, [T::Color; 178]: AsMilliwatts + 'static {
type Output = T::Color;
fn sample(&mut self, rect: &Rectangle<BikeSpace>) -> impl Iterator<Item = (Coordinates<BikeSpace>, &'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<BikeSpace>,
end: Coordinates<BikeSpace>
}
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<BikeSpace>, &'a mut P::Format);
fn next(&mut self) -> Option<Self::Item> {
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]))
}
}