use core::fmt::Debug;
use core::marker::PhantomData;
use heapless::Vec;
use crate::color::{ColorCorrection, FromColor};
use crate::driver::Driver;
#[cfg(feature = "async")]
use crate::driver::DriverAsync;
mod delay;
mod spi;
pub use self::delay::*;
pub trait ClockedLed {
type Word;
type Color;
fn start() -> impl IntoIterator<Item = Self::Word>;
fn led(
color: Self::Color,
brightness: f32,
correction: ColorCorrection,
) -> impl IntoIterator<Item = Self::Word>;
fn end(pixel_count: usize) -> impl IntoIterator<Item = Self::Word>;
fn update<I>(
pixels: I,
brightness: f32,
correction: ColorCorrection,
pixel_count: usize,
) -> impl IntoIterator<Item = Self::Word>
where
I: IntoIterator<Item = Self::Color>,
{
Self::start()
.into_iter()
.chain(
pixels
.into_iter()
.flat_map(move |color| Self::led(color, brightness, correction).into_iter()),
)
.chain(Self::end(pixel_count))
}
}
pub trait ClockedWriter<Word> {
type Error;
fn write<Words>(&mut self, words: Words) -> Result<(), Self::Error>
where
Words: AsRef<[Word]>;
}
#[cfg(feature = "async")]
pub trait ClockedWriterAsync<Word> {
type Error;
#[allow(async_fn_in_trait)]
async fn write<Words>(&mut self, words: Words) -> Result<(), Self::Error>
where
Words: AsRef<[Word]>;
}
#[derive(Debug)]
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
pub struct ClockedDriver<Led, Writer> {
led: PhantomData<Led>,
writer: Writer,
}
impl Default for ClockedDriver<(), ()> {
fn default() -> Self {
ClockedDriver {
led: PhantomData,
writer: (),
}
}
}
impl<Writer> ClockedDriver<(), Writer> {
pub fn with_led<Led>(self) -> ClockedDriver<Led, Writer> {
ClockedDriver {
led: PhantomData,
writer: self.writer,
}
}
}
impl<Led> ClockedDriver<Led, ()> {
pub fn with_writer<Writer>(self, writer: Writer) -> ClockedDriver<Led, Writer> {
ClockedDriver {
led: self.led,
writer,
}
}
}
impl<Led, Writer> Driver for ClockedDriver<Led, Writer>
where
Led: ClockedLed,
Writer: ClockedWriter<Led::Word>,
{
type Error = Writer::Error;
type Color = Led::Color;
type Word = Led::Word;
fn encode<const PIXEL_COUNT: usize, const FRAME_BUFFER_SIZE: usize, I, C>(
&mut self,
pixels: I,
brightness: f32,
correction: ColorCorrection,
) -> Vec<Self::Word, FRAME_BUFFER_SIZE>
where
I: IntoIterator<Item = C>,
Led::Color: FromColor<C>,
{
let pixels = pixels.into_iter().map(Led::Color::from_color);
let frame: Vec<_, FRAME_BUFFER_SIZE> =
Vec::from_iter(Led::update(pixels, brightness, correction, PIXEL_COUNT));
frame
}
fn write<const FRAME_BUFFER_SIZE: usize>(
&mut self,
frame: Vec<Self::Word, FRAME_BUFFER_SIZE>,
_brightness: f32,
_correction: ColorCorrection,
) -> Result<(), Self::Error> {
self.writer.write(frame)
}
}
#[cfg(feature = "async")]
impl<Led, Writer> DriverAsync for ClockedDriver<Led, Writer>
where
Led: ClockedLed,
Writer: ClockedWriterAsync<Led::Word>,
{
type Error = Writer::Error;
type Color = Led::Color;
type Word = Led::Word;
fn encode<const PIXEL_COUNT: usize, const FRAME_BUFFER_SIZE: usize, I, C>(
&mut self,
pixels: I,
brightness: f32,
correction: ColorCorrection,
) -> Vec<Self::Word, FRAME_BUFFER_SIZE>
where
I: IntoIterator<Item = C>,
Led::Color: FromColor<C>,
{
let pixels = pixels.into_iter().map(Led::Color::from_color);
let frame: Vec<_, FRAME_BUFFER_SIZE> =
Vec::from_iter(Led::update(pixels, brightness, correction, PIXEL_COUNT));
frame
}
async fn write<const FRAME_BUFFER_SIZE: usize>(
&mut self,
frame: Vec<Self::Word, FRAME_BUFFER_SIZE>,
) -> Result<(), Self::Error> {
self.writer.write(frame).await
}
}