use core::sync::atomic::{compiler_fence, Ordering};
use super::{
single_channel::{ChannelConfig, SingleChannel},
Pace, ReadTarget, WriteTarget,
};
pub struct Config<CH1, CH2, FROM, BIDI, TO>
where
CH1: SingleChannel,
CH2: SingleChannel,
FROM: ReadTarget,
BIDI: ReadTarget + WriteTarget,
TO: WriteTarget,
{
ch: (CH1, CH2),
from: FROM,
bidi: BIDI,
to: TO,
from_pace: Pace,
to_pace: Pace,
bswap: bool,
}
impl<CH1, CH2, FROM, BIDI, TO, WORD> Config<CH1, CH2, FROM, BIDI, TO>
where
CH1: SingleChannel,
CH2: SingleChannel,
FROM: ReadTarget<ReceivedWord = WORD>,
BIDI: ReadTarget<ReceivedWord = WORD> + WriteTarget<TransmittedWord = WORD>,
TO: WriteTarget<TransmittedWord = WORD>,
{
pub fn new(ch: (CH1, CH2), from: FROM, bidi: BIDI, to: TO) -> Config<CH1, CH2, FROM, BIDI, TO> {
Config {
ch,
from,
bidi,
to,
bswap: false,
from_pace: Pace::PreferSink,
to_pace: Pace::PreferSink,
}
}
#[allow(clippy::wrong_self_convention)]
pub fn from_pace(&mut self, pace: Pace) {
self.from_pace = pace;
}
#[allow(clippy::wrong_self_convention)]
pub fn to_pace(&mut self, pace: Pace) {
self.to_pace = pace;
}
pub fn bswap(&mut self, bswap: bool) {
self.bswap = bswap;
}
pub fn start(mut self) -> Transfer<CH1, CH2, FROM, BIDI, TO> {
cortex_m::asm::dsb();
compiler_fence(Ordering::SeqCst);
self.ch.0.config(
&self.from,
&mut self.bidi,
self.from_pace,
self.bswap,
None,
false,
);
self.ch.1.config(
&self.bidi,
&mut self.to,
self.to_pace,
self.bswap,
None,
false,
);
self.ch.0.start_both(&mut self.ch.1);
Transfer {
ch: self.ch,
from: self.from,
bidi: self.bidi,
to: self.to,
}
}
}
pub struct Transfer<CH1, CH2, FROM, BIDI, TO>
where
CH1: SingleChannel,
CH2: SingleChannel,
FROM: ReadTarget,
BIDI: ReadTarget + WriteTarget,
TO: WriteTarget,
{
ch: (CH1, CH2),
from: FROM,
bidi: BIDI,
to: TO,
}
impl<CH1, CH2, FROM, BIDI, TO, WORD> Transfer<CH1, CH2, FROM, BIDI, TO>
where
CH1: SingleChannel,
CH2: SingleChannel,
FROM: ReadTarget<ReceivedWord = WORD>,
BIDI: ReadTarget<ReceivedWord = WORD> + WriteTarget<TransmittedWord = WORD>,
TO: WriteTarget<TransmittedWord = WORD>,
{
pub fn check_irq0(&mut self) -> bool {
let a = self.ch.0.check_irq0();
let b = self.ch.1.check_irq0();
a | b
}
pub fn check_irq1(&mut self) -> bool {
let a = self.ch.0.check_irq1();
let b = self.ch.1.check_irq1();
a | b
}
pub fn is_done(&self) -> bool {
let a = self.ch.1.ch().ch_ctrl_trig().read().busy().bit_is_set();
let b = self.ch.0.ch().ch_ctrl_trig().read().busy().bit_is_set();
!(a | b)
}
pub fn wait(self) -> ((CH1, CH2), FROM, BIDI, TO) {
while !self.is_done() {}
cortex_m::asm::dsb();
compiler_fence(Ordering::SeqCst);
((self.ch.0, self.ch.1), self.from, self.bidi, self.to)
}
}