198 lines
6.5 KiB
Rust
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]))
|
|
}
|
|
} |