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