use embedded_hal::{delay::DelayNs, digital::OutputPin};
#[cfg(feature = "async")]
use embedded_hal_async::delay::DelayNs as DelayNsAsync;
use crate::{
time::{Megahertz, Nanoseconds},
util::bits::{word_to_bits_msb, Word as WordTrait},
};
use super::ClockedWriter;
#[cfg(feature = "async")]
use super::ClockedWriterAsync;
pub struct ClockedDelayBuilder<Data, Clock, Delay, DataRate> {
data: Data,
clock: Clock,
delay: Delay,
data_rate: DataRate,
}
impl Default for ClockedDelayBuilder<(), (), (), ()> {
fn default() -> Self {
Self {
data: (),
clock: (),
delay: (),
data_rate: (),
}
}
}
impl<Clock, Delay, DataRate> ClockedDelayBuilder<(), Clock, Delay, DataRate> {
pub fn with_data<Data: OutputPin>(
self,
data: Data,
) -> ClockedDelayBuilder<Data, Clock, Delay, DataRate> {
ClockedDelayBuilder {
data,
clock: self.clock,
delay: self.delay,
data_rate: self.data_rate,
}
}
}
impl<Data, Delay, DataRate> ClockedDelayBuilder<Data, (), Delay, DataRate> {
pub fn with_clock<Clock: OutputPin>(
self,
clock: Clock,
) -> ClockedDelayBuilder<Data, Clock, Delay, DataRate> {
ClockedDelayBuilder {
data: self.data,
clock,
delay: self.delay,
data_rate: self.data_rate,
}
}
}
impl<Data, Clock, DataRate> ClockedDelayBuilder<Data, Clock, (), DataRate> {
pub fn with_delay<Delay>(
self,
delay: Delay,
) -> ClockedDelayBuilder<Data, Clock, Delay, DataRate> {
ClockedDelayBuilder {
data: self.data,
clock: self.clock,
delay,
data_rate: self.data_rate,
}
}
}
impl<Data, Clock, Delay> ClockedDelayBuilder<Data, Clock, Delay, ()> {
pub fn with_data_rate(
self,
data_rate: Megahertz,
) -> ClockedDelayBuilder<Data, Clock, Delay, Megahertz> {
ClockedDelayBuilder {
data: self.data,
clock: self.clock,
delay: self.delay,
data_rate,
}
}
}
impl<Data, Clock, Delay> ClockedDelayBuilder<Data, Clock, Delay, Megahertz>
where
Data: OutputPin,
Clock: OutputPin,
{
pub fn build(self) -> ClockedDelay<Data, Clock, Delay> {
ClockedDelay::new(self.data, self.clock, self.delay, self.data_rate)
}
}
#[derive(Debug)]
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
pub struct ClockedDelay<Data, Clock, Delay>
where
Data: OutputPin,
Clock: OutputPin,
{
data: Data,
clock: Clock,
delay: Delay,
t_half_cycle_ns: u32,
}
impl<Data, Clock, Delay> ClockedDelay<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)]
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
pub enum ClockedDelayError<Data, Clock>
where
Data: OutputPin,
Clock: OutputPin,
{
Data(Data::Error),
Clock(Clock::Error),
}
impl<Word, Data, Clock, Delay> ClockedWriter<Word> for ClockedDelay<Data, Clock, Delay>
where
Word: WordTrait,
Data: OutputPin,
Clock: OutputPin,
Delay: DelayNs,
{
type Error = ClockedDelayError<Data, Clock>;
fn write<Words>(&mut self, words: Words) -> Result<(), Self::Error>
where
Words: AsRef<[Word]>,
{
for word in words.as_ref() {
for bit in word_to_bits_msb(*word) {
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<Word, Data, Clock, Delay> ClockedWriterAsync<Word> for ClockedDelay<Data, Clock, Delay>
where
Word: WordTrait,
Data: OutputPin,
Clock: OutputPin,
Delay: DelayNsAsync,
{
type Error = ClockedDelayError<Data, Clock>;
async fn write<Words>(&mut self, words: Words) -> Result<(), Self::Error>
where
Words: AsRef<[Word]>,
{
for word in words.as_ref() {
for bit in word_to_bits_msb(*word) {
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(())
}
}