use core::marker::PhantomData;
use embedded_hal::{delay::DelayNs, digital::OutputPin};
#[cfg(feature = "async")]
use embedded_hal_async::delay::DelayNs as DelayNsAsync;
use heapless::Vec;
use super::ClocklessLed;
#[cfg(feature = "async")]
use crate::driver::ClocklessWriterAsync;
use crate::{
driver::ClocklessWriter,
util::bits::{word_to_bits_msb, Word},
};
pub struct ClocklessDelayBuilder<Led, Data, Delay> {
led: PhantomData<Led>,
data: Data,
delay: Delay,
}
impl Default for ClocklessDelayBuilder<(), (), ()> {
fn default() -> Self {
Self {
led: PhantomData,
data: (),
delay: (),
}
}
}
impl<Data, Delay> ClocklessDelayBuilder<(), Data, Delay> {
pub fn with_led<Led: ClocklessLed>(self) -> ClocklessDelayBuilder<Led, Data, Delay> {
ClocklessDelayBuilder {
led: PhantomData,
data: self.data,
delay: self.delay,
}
}
}
impl<Led, Delay> ClocklessDelayBuilder<Led, (), Delay> {
pub fn with_data<Data: OutputPin>(self, data: Data) -> ClocklessDelayBuilder<Led, Data, Delay> {
ClocklessDelayBuilder {
led: self.led,
data,
delay: self.delay,
}
}
}
impl<Led, Data> ClocklessDelayBuilder<Led, Data, ()> {
pub fn with_delay<Delay>(self, delay: Delay) -> ClocklessDelayBuilder<Led, Data, Delay> {
ClocklessDelayBuilder {
led: self.led,
data: self.data,
delay,
}
}
}
impl<Led, Data, Delay> ClocklessDelayBuilder<Led, Data, Delay>
where
Data: OutputPin,
Led: ClocklessLed,
{
pub fn build(self) -> ClocklessDelay<Led, Data, Delay> {
ClocklessDelay::new(self.data, self.delay)
}
}
pub struct ClocklessDelay<Led: ClocklessLed, Data: OutputPin, Delay> {
led: PhantomData<Led>,
data: Data,
delay: Delay,
}
impl<Led, Data, Delay> ClocklessDelay<Led, Data, Delay>
where
Led: ClocklessLed,
Data: OutputPin,
{
pub fn new(data: Data, delay: Delay) -> Self {
Self {
led: PhantomData,
data,
delay,
}
}
}
impl<Led, Data, Delay> ClocklessWriter<Led> for ClocklessDelay<Led, Data, Delay>
where
Led: ClocklessLed,
Led::Word: Word,
Data: OutputPin,
Delay: DelayNs,
{
type Error = Data::Error;
fn write<const FRAME_BUFFER_SIZE: usize>(
&mut self,
frame: Vec<Led::Word, FRAME_BUFFER_SIZE>,
) -> Result<(), Self::Error> {
for byte in frame {
for bit in word_to_bits_msb(byte) {
if !bit {
self.data.set_high()?;
self.delay.delay_ns(Led::T_0H.to_nanos());
self.data.set_low()?;
self.delay.delay_ns(Led::T_0L.to_nanos());
} else {
self.data.set_high()?;
self.delay.delay_ns(Led::T_1H.to_nanos());
self.data.set_low()?;
self.delay.delay_ns(Led::T_1L.to_nanos());
}
}
}
self.delay.delay_ns(Led::T_RESET.to_nanos());
Ok(())
}
}
#[cfg(feature = "async")]
impl<Led, Data, Delay> ClocklessWriterAsync<Led> for ClocklessDelay<Led, Data, Delay>
where
Led: ClocklessLed,
Led::Word: Word,
Data: OutputPin,
Delay: DelayNsAsync,
{
type Error = Data::Error;
async fn write<const FRAME_BUFFER_SIZE: usize>(
&mut self,
frame: Vec<Led::Word, FRAME_BUFFER_SIZE>,
) -> Result<(), Self::Error> {
for byte in frame {
for bit in word_to_bits_msb(byte) {
if !bit {
self.data.set_high()?;
self.delay.delay_ns(Led::T_0H.to_nanos()).await;
self.data.set_low()?;
self.delay.delay_ns(Led::T_0L.to_nanos()).await;
} else {
self.data.set_high()?;
self.delay.delay_ns(Led::T_1H.to_nanos()).await;
self.data.set_low()?;
self.delay.delay_ns(Led::T_1L.to_nanos()).await;
}
}
}
self.delay.delay_ns(Led::T_RESET.to_nanos()).await;
Ok(())
}
}