use core::marker::PhantomData;
use embedded_hal::{delay::DelayNs, digital::OutputPin};
#[cfg(feature = "async")]
use embedded_hal_async::delay::DelayNs as DelayNsAsync;
#[cfg(feature = "async")]
use crate::driver::DriverAsync;
use crate::{
color::{ColorCorrection, FromColor},
driver::Driver,
time::{Megahertz, Nanoseconds},
util::bits::{u8_to_bits, BitOrder},
};
use super::{ClockedLed, ClockedWriter};
#[cfg(feature = "async")]
use super::{ClockedLedAsync, ClockedWriterAsync};
#[derive(Debug)]
pub struct ClockedDelayDriver<Led, Data, Clock, Delay>
where
Data: OutputPin,
Clock: OutputPin,
{
led: PhantomData<Led>,
writer: ClockedDelayWriter<Data, Clock, Delay>,
}
impl<Led, Data, Clock, Delay> ClockedDelayDriver<Led, Data, Clock, Delay>
where
Data: OutputPin,
Clock: OutputPin,
{
pub fn new(data: Data, clock: Clock, delay: Delay, data_rate: Megahertz) -> Self {
Self {
led: PhantomData,
writer: ClockedDelayWriter::new(data, clock, delay, data_rate),
}
}
}
impl<Led, Data, Clock, Delay> Driver for ClockedDelayDriver<Led, Data, Clock, Delay>
where
Led: ClockedLed<Word = u8>,
Data: OutputPin,
Clock: OutputPin,
Delay: DelayNs,
{
type Error = ClockedDelayError<Data, Clock>;
type Color = Led::Color;
fn write<I, C>(
&mut self,
pixels: I,
brightness: f32,
correction: ColorCorrection,
) -> Result<(), Self::Error>
where
I: IntoIterator<Item = C>,
Self::Color: FromColor<C>,
{
Led::clocked_write(&mut self.writer, pixels, brightness, correction)
}
}
#[cfg(feature = "async")]
impl<Led, Data, Clock, Delay> DriverAsync for ClockedDelayDriver<Led, Data, Clock, Delay>
where
Led: ClockedLedAsync<Word = u8>,
Data: OutputPin,
Clock: OutputPin,
Delay: DelayNsAsync,
{
type Error = ClockedDelayError<Data, Clock>;
type Color = Led::Color;
async fn write<I, C>(
&mut self,
pixels: I,
brightness: f32,
correction: ColorCorrection,
) -> Result<(), Self::Error>
where
I: IntoIterator<Item = C>,
Self::Color: FromColor<C>,
{
Led::clocked_write(&mut self.writer, pixels, brightness, correction).await
}
}
#[derive(Debug)]
pub struct ClockedDelayWriter<Data, Clock, Delay>
where
Data: OutputPin,
Clock: OutputPin,
{
data: Data,
clock: Clock,
delay: Delay,
t_half_cycle_ns: u32,
}
impl<Data, Clock, Delay> ClockedDelayWriter<Data, Clock, Delay>
where
Data: OutputPin,
Clock: OutputPin,
{
pub fn new(data: Data, clock: Clock, delay: Delay, data_rate: Megahertz) -> Self {
let t_cycle: Nanoseconds = data_rate.into_duration();
let t_half_cycle = t_cycle / 2;
let t_half_cycle_ns = t_half_cycle.to_nanos();
Self {
data,
clock,
delay,
t_half_cycle_ns,
}
}
}
#[derive(Debug)]
pub enum ClockedDelayError<Data, Clock>
where
Data: OutputPin,
Clock: OutputPin,
{
Data(Data::Error),
Clock(Clock::Error),
}
impl<Data, Clock, Delay> ClockedWriter for ClockedDelayWriter<Data, Clock, Delay>
where
Data: OutputPin,
Clock: OutputPin,
Delay: DelayNs,
{
type Error = ClockedDelayError<Data, Clock>;
type Word = u8;
fn write(&mut self, words: &[Self::Word]) -> Result<(), Self::Error> {
for byte in words {
for bit in u8_to_bits(byte, BitOrder::MostSignificantBit) {
match bit {
false => self.data.set_low(),
true => self.data.set_high(),
}
.map_err(ClockedDelayError::Data)?;
self.delay.delay_ns(self.t_half_cycle_ns);
self.clock.set_high().map_err(ClockedDelayError::Clock)?;
self.delay.delay_ns(self.t_half_cycle_ns);
self.clock.set_low().map_err(ClockedDelayError::Clock)?;
}
}
Ok(())
}
}
#[cfg(feature = "async")]
impl<Data, Clock, Delay> ClockedWriterAsync for ClockedDelayWriter<Data, Clock, Delay>
where
Data: OutputPin,
Clock: OutputPin,
Delay: DelayNsAsync,
{
type Error = ClockedDelayError<Data, Clock>;
type Word = u8;
async fn write(&mut self, words: &[Self::Word]) -> Result<(), Self::Error> {
for byte in words {
for bit in u8_to_bits(byte, BitOrder::MostSignificantBit) {
match bit {
false => self.data.set_low(),
true => self.data.set_high(),
}
.map_err(ClockedDelayError::Data)?;
self.delay.delay_ns(self.t_half_cycle_ns).await;
self.clock.set_high().map_err(ClockedDelayError::Clock)?;
self.delay.delay_ns(self.t_half_cycle_ns).await;
self.clock.set_low().map_err(ClockedDelayError::Clock)?;
}
}
Ok(())
}
}