1use core::sync::atomic::{compiler_fence, Ordering};
4
5use super::{
6 single_channel::ChannelConfig, single_channel::SingleChannel, EndlessReadTarget,
7 EndlessWriteTarget, Pace, ReadTarget, WriteTarget,
8};
9
10pub struct Config<CH1: SingleChannel, CH2: SingleChannel, FROM: ReadTarget, TO: WriteTarget> {
12 ch: (CH1, CH2),
13 from: FROM,
14 to: TO,
15 bswap: bool,
16 pace: Pace,
17}
18
19impl<CH1, CH2, FROM, TO, WORD> Config<CH1, CH2, FROM, TO>
20where
21 CH1: SingleChannel,
22 CH2: SingleChannel,
23 FROM: ReadTarget<ReceivedWord = WORD>,
24 TO: WriteTarget<TransmittedWord = WORD>,
25{
26 pub fn new(ch: (CH1, CH2), from: FROM, to: TO) -> Config<CH1, CH2, FROM, TO> {
28 Config {
29 ch,
30 from,
31 to,
32 bswap: false,
33 pace: Pace::PreferSource,
34 }
35 }
36
37 pub fn pace(&mut self, pace: Pace) {
43 self.pace = pace;
44 }
45
46 pub fn bswap(&mut self, bswap: bool) {
54 self.bswap = bswap;
55 }
56
57 pub fn start(mut self) -> Transfer<CH1, CH2, FROM, TO, ()> {
59 cortex_m::asm::dsb();
64 compiler_fence(Ordering::SeqCst);
65
66 self.ch
68 .0
69 .config(&self.from, &mut self.to, self.pace, self.bswap, None, true);
70
71 Transfer {
72 ch: self.ch,
73 from: self.from,
74 to: self.to,
75 pace: self.pace,
76 bswap: self.bswap,
77 state: (),
78 second_ch: false,
79 }
80 }
81}
82
83pub struct ReadNext<BUF: ReadTarget>(BUF);
85pub struct WriteNext<BUF: WriteTarget>(BUF);
87
88pub struct Transfer<CH1, CH2, FROM, TO, STATE>
90where
91 CH1: SingleChannel,
92 CH2: SingleChannel,
93 FROM: ReadTarget,
94 TO: WriteTarget,
95{
96 ch: (CH1, CH2),
97 from: FROM,
98 to: TO,
99 pace: Pace,
100 bswap: bool,
101 state: STATE,
102 second_ch: bool,
103}
104
105impl<CH1, CH2, FROM, TO, WORD, STATE> Transfer<CH1, CH2, FROM, TO, STATE>
106where
107 CH1: SingleChannel,
108 CH2: SingleChannel,
109 FROM: ReadTarget<ReceivedWord = WORD>,
110 TO: WriteTarget<TransmittedWord = WORD>,
111{
112 pub fn check_irq0(&mut self) -> bool {
114 if self.second_ch {
115 self.ch.1.check_irq0()
116 } else {
117 self.ch.0.check_irq0()
118 }
119 }
120
121 pub fn check_irq1(&mut self) -> bool {
123 if self.second_ch {
124 self.ch.1.check_irq1()
125 } else {
126 self.ch.0.check_irq1()
127 }
128 }
129
130 pub fn is_done(&self) -> bool {
132 if self.second_ch {
133 !self.ch.1.ch().ch_ctrl_trig().read().busy().bit_is_set()
134 } else {
135 !self.ch.0.ch().ch_ctrl_trig().read().busy().bit_is_set()
136 }
137 }
138}
139
140impl<CH1, CH2, FROM, TO, WORD> Transfer<CH1, CH2, FROM, TO, ()>
141where
142 CH1: SingleChannel,
143 CH2: SingleChannel,
144 FROM: ReadTarget<ReceivedWord = WORD>,
145 TO: WriteTarget<TransmittedWord = WORD> + EndlessWriteTarget,
146{
147 pub fn wait(self) -> (CH1, CH2, FROM, TO) {
149 while !self.is_done() {}
150
151 cortex_m::asm::dsb();
153 compiler_fence(Ordering::SeqCst);
154
155 (self.ch.0, self.ch.1, self.from, self.to)
157 }
158}
159
160impl<CH1, CH2, FROM, TO, WORD> Transfer<CH1, CH2, FROM, TO, ()>
161where
162 CH1: SingleChannel,
163 CH2: SingleChannel,
164 FROM: ReadTarget<ReceivedWord = WORD>,
165 TO: WriteTarget<TransmittedWord = WORD> + EndlessWriteTarget,
166{
167 pub fn read_next<BUF: ReadTarget<ReceivedWord = WORD>>(
169 mut self,
170 buf: BUF,
171 ) -> Transfer<CH1, CH2, FROM, TO, ReadNext<BUF>> {
172 cortex_m::asm::dsb();
175 compiler_fence(Ordering::SeqCst);
176
177 if self.second_ch {
179 self.ch
180 .0
181 .config(&buf, &mut self.to, self.pace, self.bswap, None, false);
182 } else {
183 self.ch
184 .1
185 .config(&buf, &mut self.to, self.pace, self.bswap, None, false);
186 }
187
188 if self.second_ch {
190 self.ch.1.set_chain_to_enabled(&mut self.ch.0);
191 } else {
192 self.ch.0.set_chain_to_enabled(&mut self.ch.1);
193 }
194
195 Transfer {
196 ch: self.ch,
197 from: self.from,
198 to: self.to,
199 pace: self.pace,
200 bswap: self.bswap,
201 state: ReadNext(buf),
202 second_ch: self.second_ch,
203 }
204 }
205}
206
207impl<CH1, CH2, FROM, TO, WORD> Transfer<CH1, CH2, FROM, TO, ()>
208where
209 CH1: SingleChannel,
210 CH2: SingleChannel,
211 FROM: ReadTarget<ReceivedWord = WORD> + EndlessReadTarget,
212 TO: WriteTarget<TransmittedWord = WORD>,
213{
214 pub fn write_next<BUF: WriteTarget<TransmittedWord = WORD>>(
216 mut self,
217 mut buf: BUF,
218 ) -> Transfer<CH1, CH2, FROM, TO, WriteNext<BUF>> {
219 cortex_m::asm::dsb();
222 compiler_fence(Ordering::SeqCst);
223
224 if self.second_ch {
226 self.ch
227 .0
228 .config(&self.from, &mut buf, self.pace, self.bswap, None, false);
229 } else {
230 self.ch
231 .1
232 .config(&self.from, &mut buf, self.pace, self.bswap, None, false);
233 }
234
235 if self.second_ch {
237 self.ch.1.set_chain_to_enabled(&mut self.ch.0);
238 } else {
239 self.ch.0.set_chain_to_enabled(&mut self.ch.1);
240 }
241
242 Transfer {
243 ch: self.ch,
244 from: self.from,
245 to: self.to,
246 pace: self.pace,
247 bswap: self.bswap,
248 state: WriteNext(buf),
249 second_ch: self.second_ch,
250 }
251 }
252}
253
254impl<CH1, CH2, FROM, TO, NEXT, WORD> Transfer<CH1, CH2, FROM, TO, ReadNext<NEXT>>
255where
256 CH1: SingleChannel,
257 CH2: SingleChannel,
258 FROM: ReadTarget<ReceivedWord = WORD>,
259 TO: WriteTarget<TransmittedWord = WORD> + EndlessWriteTarget,
260 NEXT: ReadTarget<ReceivedWord = WORD>,
261{
262 pub fn wait(self) -> (FROM, Transfer<CH1, CH2, NEXT, TO, ()>) {
264 while !self.is_done() {}
265
266 cortex_m::asm::dsb();
268 compiler_fence(Ordering::SeqCst);
269
270 (
272 self.from,
273 Transfer {
274 ch: self.ch,
275 from: self.state.0,
276 to: self.to,
277 pace: self.pace,
278 bswap: self.bswap,
279 state: (),
280 second_ch: !self.second_ch,
281 },
282 )
283 }
284}
285
286impl<CH1, CH2, FROM, TO, NEXT, WORD> Transfer<CH1, CH2, FROM, TO, WriteNext<NEXT>>
287where
288 CH1: SingleChannel,
289 CH2: SingleChannel,
290 FROM: ReadTarget<ReceivedWord = WORD> + EndlessReadTarget,
291 TO: WriteTarget<TransmittedWord = WORD>,
292 NEXT: WriteTarget<TransmittedWord = WORD>,
293{
294 pub fn wait(self) -> (TO, Transfer<CH1, CH2, FROM, NEXT, ()>) {
296 while !self.is_done() {}
297
298 cortex_m::asm::dsb();
300 compiler_fence(Ordering::SeqCst);
301
302 (
304 self.to,
305 Transfer {
306 ch: self.ch,
307 from: self.from,
308 to: self.state.0,
309 pace: self.pace,
310 bswap: self.bswap,
311 state: (),
312 second_ch: !self.second_ch,
313 },
314 )
315 }
316}