1use enumset::EnumSet;
2use portable_atomic::{AtomicBool, Ordering};
3
4use crate::{
5 asynch::AtomicWaker,
6 dma::{
7 BurstConfig,
8 DmaChannel,
9 DmaPeripheral,
10 DmaRxChannel,
11 DmaRxInterrupt,
12 DmaTxChannel,
13 DmaTxInterrupt,
14 InterruptAccess,
15 PdmaChannel,
16 RegisterAccess,
17 RxRegisterAccess,
18 TxRegisterAccess,
19 },
20 interrupt::InterruptHandler,
21 peripherals::Interrupt,
22};
23
24pub(super) type I2sRegisterBlock = crate::pac::i2s0::RegisterBlock;
25
26#[derive(Debug)]
28#[cfg_attr(feature = "defmt", derive(defmt::Format))]
29pub struct AnyI2sDmaRxChannel<'d>(pub(crate) AnyI2sDmaChannel<'d>);
30
31impl AnyI2sDmaRxChannel<'_> {
32 fn regs(&self) -> &I2sRegisterBlock {
33 self.0.register_block()
34 }
35}
36
37impl crate::private::Sealed for AnyI2sDmaRxChannel<'_> {}
38impl DmaRxChannel for AnyI2sDmaRxChannel<'_> {}
39
40#[derive(Debug)]
42#[cfg_attr(feature = "defmt", derive(defmt::Format))]
43pub struct AnyI2sDmaTxChannel<'d>(pub(crate) AnyI2sDmaChannel<'d>);
44
45impl AnyI2sDmaTxChannel<'_> {
46 fn regs(&self) -> &I2sRegisterBlock {
47 self.0.register_block()
48 }
49}
50
51impl crate::private::Sealed for AnyI2sDmaTxChannel<'_> {}
52impl DmaTxChannel for AnyI2sDmaTxChannel<'_> {}
53
54impl RegisterAccess for AnyI2sDmaTxChannel<'_> {
55 fn reset(&self) {
56 self.regs().lc_conf().modify(|_, w| w.out_rst().set_bit());
57 self.regs().lc_conf().modify(|_, w| w.out_rst().clear_bit());
58 }
59
60 fn set_burst_mode(&self, burst_mode: BurstConfig) {
61 self.regs()
62 .lc_conf()
63 .modify(|_, w| w.out_data_burst_en().bit(burst_mode.is_burst_enabled()));
64 }
65
66 fn set_descr_burst_mode(&self, burst_mode: bool) {
67 self.regs()
68 .lc_conf()
69 .modify(|_, w| w.outdscr_burst_en().bit(burst_mode));
70 }
71
72 fn set_link_addr(&self, address: u32) {
73 self.regs()
74 .out_link()
75 .modify(|_, w| unsafe { w.outlink_addr().bits(address) });
76 }
77
78 fn set_peripheral(&self, _peripheral: u8) {
79 }
81
82 fn start(&self) {
83 self.regs()
84 .out_link()
85 .modify(|_, w| w.outlink_start().set_bit());
86 }
87
88 fn stop(&self) {
89 self.regs()
90 .out_link()
91 .modify(|_, w| w.outlink_stop().set_bit());
92 }
93
94 fn restart(&self) {
95 self.regs()
96 .out_link()
97 .modify(|_, w| w.outlink_restart().set_bit());
98 }
99
100 fn set_check_owner(&self, check_owner: Option<bool>) {
101 self.regs()
102 .lc_conf()
103 .modify(|_, w| w.check_owner().bit(check_owner.unwrap_or(true)));
104 }
105
106 fn is_compatible_with(&self, peripheral: DmaPeripheral) -> bool {
107 self.0.is_compatible_with(peripheral)
108 }
109
110 #[cfg(psram_dma)]
111 fn set_ext_mem_block_size(&self, size: crate::dma::DmaExtMemBKSize) {
112 self.regs()
113 .lc_conf()
114 .modify(|_, w| unsafe { w.ext_mem_bk_size().bits(size as u8) });
115 }
116
117 #[cfg(psram_dma)]
118 fn can_access_psram(&self) -> bool {
119 matches!(self.0, AnyI2sDmaChannel(any::Inner::I2s0(_)))
120 }
121}
122
123impl TxRegisterAccess for AnyI2sDmaTxChannel<'_> {
124 fn is_fifo_empty(&self) -> bool {
125 cfg_if::cfg_if! {
126 if #[cfg(esp32)] {
127 self.regs().lc_state0().read().bits() & 0x80000000 != 0
128 } else {
129 self.regs().lc_state0().read().out_empty().bit_is_set()
130 }
131 }
132 }
133
134 fn set_auto_write_back(&self, enable: bool) {
135 self.regs()
136 .lc_conf()
137 .modify(|_, w| w.out_auto_wrback().bit(enable));
138 }
139
140 fn last_dscr_address(&self) -> usize {
141 self.regs()
142 .out_eof_des_addr()
143 .read()
144 .out_eof_des_addr()
145 .bits() as usize
146 }
147
148 fn peripheral_interrupt(&self) -> Option<Interrupt> {
149 Some(self.0.peripheral_interrupt())
150 }
151
152 fn async_handler(&self) -> Option<InterruptHandler> {
153 Some(self.0.async_handler())
154 }
155}
156
157impl InterruptAccess<DmaTxInterrupt> for AnyI2sDmaTxChannel<'_> {
158 fn enable_listen(&self, interrupts: EnumSet<DmaTxInterrupt>, enable: bool) {
159 self.regs().int_ena().modify(|_, w| {
160 for interrupt in interrupts {
161 match interrupt {
162 DmaTxInterrupt::TotalEof => w.out_total_eof().bit(enable),
163 DmaTxInterrupt::DescriptorError => w.out_dscr_err().bit(enable),
164 DmaTxInterrupt::Eof => w.out_eof().bit(enable),
165 DmaTxInterrupt::Done => w.out_done().bit(enable),
166 };
167 }
168 w
169 });
170 }
171
172 fn is_listening(&self) -> EnumSet<DmaTxInterrupt> {
173 let mut result = EnumSet::new();
174
175 let int_ena = self.regs().int_ena().read();
176 if int_ena.out_total_eof().bit_is_set() {
177 result |= DmaTxInterrupt::TotalEof;
178 }
179 if int_ena.out_dscr_err().bit_is_set() {
180 result |= DmaTxInterrupt::DescriptorError;
181 }
182 if int_ena.out_eof().bit_is_set() {
183 result |= DmaTxInterrupt::Eof;
184 }
185 if int_ena.out_done().bit_is_set() {
186 result |= DmaTxInterrupt::Done;
187 }
188
189 result
190 }
191
192 fn pending_interrupts(&self) -> EnumSet<DmaTxInterrupt> {
193 let mut result = EnumSet::new();
194
195 let int_raw = self.regs().int_raw().read();
196 if int_raw.out_total_eof().bit_is_set() {
197 result |= DmaTxInterrupt::TotalEof;
198 }
199 if int_raw.out_dscr_err().bit_is_set() {
200 result |= DmaTxInterrupt::DescriptorError;
201 }
202 if int_raw.out_eof().bit_is_set() {
203 result |= DmaTxInterrupt::Eof;
204 }
205 if int_raw.out_done().bit_is_set() {
206 result |= DmaTxInterrupt::Done;
207 }
208
209 result
210 }
211
212 fn clear(&self, interrupts: impl Into<EnumSet<DmaTxInterrupt>>) {
213 self.regs().int_clr().write(|w| {
214 for interrupt in interrupts.into() {
215 match interrupt {
216 DmaTxInterrupt::TotalEof => w.out_total_eof().clear_bit_by_one(),
217 DmaTxInterrupt::DescriptorError => w.out_dscr_err().clear_bit_by_one(),
218 DmaTxInterrupt::Eof => w.out_eof().clear_bit_by_one(),
219 DmaTxInterrupt::Done => w.out_done().clear_bit_by_one(),
220 };
221 }
222 w
223 });
224 }
225
226 fn waker(&self) -> &'static AtomicWaker {
227 self.0.tx_waker()
228 }
229
230 fn is_async(&self) -> bool {
231 self.0.tx_async_flag().load(Ordering::Relaxed)
232 }
233
234 fn set_async(&self, _is_async: bool) {
235 self.0.tx_async_flag().store(_is_async, Ordering::Relaxed);
236 }
237}
238
239impl RegisterAccess for AnyI2sDmaRxChannel<'_> {
240 fn reset(&self) {
241 self.regs().lc_conf().modify(|_, w| w.in_rst().set_bit());
242 self.regs().lc_conf().modify(|_, w| w.in_rst().clear_bit());
243 }
244
245 fn set_burst_mode(&self, _burst_mode: BurstConfig) {}
246
247 fn set_descr_burst_mode(&self, burst_mode: bool) {
248 self.regs()
249 .lc_conf()
250 .modify(|_, w| w.indscr_burst_en().bit(burst_mode));
251 }
252
253 fn set_link_addr(&self, address: u32) {
254 self.regs()
255 .in_link()
256 .modify(|_, w| unsafe { w.inlink_addr().bits(address) });
257 }
258
259 fn set_peripheral(&self, _peripheral: u8) {
260 }
262
263 fn start(&self) {
264 self.regs()
265 .in_link()
266 .modify(|_, w| w.inlink_start().set_bit());
267 }
268
269 fn stop(&self) {
270 self.regs()
271 .in_link()
272 .modify(|_, w| w.inlink_stop().set_bit());
273 }
274
275 fn restart(&self) {
276 self.regs()
277 .in_link()
278 .modify(|_, w| w.inlink_restart().set_bit());
279 }
280
281 fn set_check_owner(&self, check_owner: Option<bool>) {
282 self.regs()
283 .lc_conf()
284 .modify(|_, w| w.check_owner().bit(check_owner.unwrap_or(true)));
285 }
286
287 fn is_compatible_with(&self, peripheral: DmaPeripheral) -> bool {
288 self.0.is_compatible_with(peripheral)
289 }
290
291 #[cfg(psram_dma)]
292 fn set_ext_mem_block_size(&self, size: crate::dma::DmaExtMemBKSize) {
293 self.regs()
294 .lc_conf()
295 .modify(|_, w| unsafe { w.ext_mem_bk_size().bits(size as u8) });
296 }
297
298 #[cfg(psram_dma)]
299 fn can_access_psram(&self) -> bool {
300 matches!(self.0, AnyI2sDmaChannel(any::Inner::I2s0(_)))
301 }
302}
303
304impl RxRegisterAccess for AnyI2sDmaRxChannel<'_> {
305 fn peripheral_interrupt(&self) -> Option<Interrupt> {
306 Some(self.0.peripheral_interrupt())
307 }
308
309 fn async_handler(&self) -> Option<InterruptHandler> {
310 Some(self.0.async_handler())
311 }
312}
313
314impl InterruptAccess<DmaRxInterrupt> for AnyI2sDmaRxChannel<'_> {
315 fn enable_listen(&self, interrupts: EnumSet<DmaRxInterrupt>, enable: bool) {
316 self.regs().int_ena().modify(|_, w| {
317 for interrupt in interrupts {
318 match interrupt {
319 DmaRxInterrupt::SuccessfulEof => w.in_suc_eof().bit(enable),
320 DmaRxInterrupt::ErrorEof => w.in_err_eof().bit(enable),
321 DmaRxInterrupt::DescriptorError => w.in_dscr_err().bit(enable),
322 DmaRxInterrupt::DescriptorEmpty => w.in_dscr_empty().bit(enable),
323 DmaRxInterrupt::Done => w.in_done().bit(enable),
324 };
325 }
326 w
327 });
328 }
329
330 fn is_listening(&self) -> EnumSet<DmaRxInterrupt> {
331 let mut result = EnumSet::new();
332
333 let int_ena = self.regs().int_ena().read();
334 if int_ena.in_dscr_err().bit_is_set() {
335 result |= DmaRxInterrupt::DescriptorError;
336 }
337 if int_ena.in_dscr_empty().bit_is_set() {
338 result |= DmaRxInterrupt::DescriptorEmpty;
339 }
340 if int_ena.in_suc_eof().bit_is_set() {
341 result |= DmaRxInterrupt::SuccessfulEof;
342 }
343 if int_ena.in_err_eof().bit_is_set() {
344 result |= DmaRxInterrupt::ErrorEof;
345 }
346 if int_ena.in_done().bit_is_set() {
347 result |= DmaRxInterrupt::Done;
348 }
349
350 result
351 }
352
353 fn pending_interrupts(&self) -> EnumSet<DmaRxInterrupt> {
354 let mut result = EnumSet::new();
355
356 let int_raw = self.regs().int_raw().read();
357 if int_raw.in_dscr_err().bit_is_set() {
358 result |= DmaRxInterrupt::DescriptorError;
359 }
360 if int_raw.in_dscr_empty().bit_is_set() {
361 result |= DmaRxInterrupt::DescriptorEmpty;
362 }
363 if int_raw.in_suc_eof().bit_is_set() {
364 result |= DmaRxInterrupt::SuccessfulEof;
365 }
366 if int_raw.in_err_eof().bit_is_set() {
367 result |= DmaRxInterrupt::ErrorEof;
368 }
369 if int_raw.in_done().bit_is_set() {
370 result |= DmaRxInterrupt::Done;
371 }
372
373 result
374 }
375
376 fn clear(&self, interrupts: impl Into<EnumSet<DmaRxInterrupt>>) {
377 self.regs().int_clr().write(|w| {
378 for interrupt in interrupts.into() {
379 match interrupt {
380 DmaRxInterrupt::SuccessfulEof => w.in_suc_eof().clear_bit_by_one(),
381 DmaRxInterrupt::ErrorEof => w.in_err_eof().clear_bit_by_one(),
382 DmaRxInterrupt::DescriptorError => w.in_dscr_err().clear_bit_by_one(),
383 DmaRxInterrupt::DescriptorEmpty => w.in_dscr_empty().clear_bit_by_one(),
384 DmaRxInterrupt::Done => w.in_done().clear_bit_by_one(),
385 };
386 }
387 w
388 });
389 }
390
391 fn waker(&self) -> &'static AtomicWaker {
392 self.0.rx_waker()
393 }
394
395 fn is_async(&self) -> bool {
396 self.0.rx_async_flag().load(Ordering::Relaxed)
397 }
398
399 fn set_async(&self, _is_async: bool) {
400 self.0.rx_async_flag().store(_is_async, Ordering::Relaxed);
401 }
402}
403
404crate::any_peripheral! {
405 pub peripheral AnyI2sDmaChannel<'d> {
407 #[cfg(soc_has_i2s0)]
408 I2s0(crate::peripherals::DMA_I2S0<'d>),
409 #[cfg(soc_has_i2s1)]
410 I2s1(crate::peripherals::DMA_I2S1<'d>),
411 }
412}
413
414impl<'d> DmaChannel for AnyI2sDmaChannel<'d> {
415 type Rx = AnyI2sDmaRxChannel<'d>;
416 type Tx = AnyI2sDmaTxChannel<'d>;
417
418 unsafe fn split_internal(self, _: crate::private::Internal) -> (Self::Rx, Self::Tx) {
419 (
420 AnyI2sDmaRxChannel(unsafe { self.clone_unchecked() }),
421 AnyI2sDmaTxChannel(unsafe { self.clone_unchecked() }),
422 )
423 }
424}
425
426impl PdmaChannel for AnyI2sDmaChannel<'_> {
427 type RegisterBlock = I2sRegisterBlock;
428
429 delegate::delegate! {
430 to match &self.0 {
431 #[cfg(soc_has_i2s0)]
432 any::Inner::I2s0(channel) => channel,
433 #[cfg(soc_has_i2s1)]
434 any::Inner::I2s1(channel) => channel,
435 } {
436 fn register_block(&self) -> &I2sRegisterBlock;
437 fn tx_waker(&self) -> &'static AtomicWaker;
438 fn rx_waker(&self) -> &'static AtomicWaker;
439 fn is_compatible_with(&self, peripheral: DmaPeripheral) -> bool;
440 fn peripheral_interrupt(&self) -> Interrupt;
441 fn async_handler(&self) -> InterruptHandler;
442 fn rx_async_flag(&self) -> &'static AtomicBool;
443 fn tx_async_flag(&self) -> &'static AtomicBool;
444 }
445 }
446}