1 /*
2 * SPDX-FileCopyrightText: 2020-2024 Espressif Systems (Shanghai) CO LTD
3 *
4 * SPDX-License-Identifier: Apache-2.0
5 */
6
7 /*******************************************************************************
8 * NOTICE
9 * The hal is not public api, don't use in application code.
10 * See readme.md in hal/include/hal/readme.md
11 ******************************************************************************/
12
13 // The LL layer for ESP32 I2S register operations
14
15 #pragma once
16
17 #include <stdbool.h>
18 #include "hal/misc.h"
19 #include "soc/i2s_periph.h"
20 #include "soc/i2s_struct.h"
21 #include "hal/i2s_types.h"
22
23 #ifdef __cplusplus
24 extern "C" {
25 #endif
26
27 // Get I2S hardware instance with giving i2s num
28 #define I2S_LL_GET_HW(num) (((num) == 0) ? (&I2S0) : (((num) == 1) ? (&I2S1) : NULL))
29
30 #define I2S_LL_AD_BCK_FACTOR (2)
31 #define I2S_LL_PDM_BCK_FACTOR (64)
32
33 #define I2S_LL_MCLK_DIVIDER_BIT_WIDTH (6)
34 #define I2S_LL_MCLK_DIVIDER_MAX ((1 << I2S_LL_MCLK_DIVIDER_BIT_WIDTH) - 1)
35
36 #define I2S_LL_BCK_MAX_PRESCALE (64)
37
38 #define I2S_LL_EVENT_RX_EOF BIT(9)
39 #define I2S_LL_EVENT_TX_EOF BIT(12)
40 #define I2S_LL_EVENT_RX_DSCR_ERR BIT(13)
41 #define I2S_LL_EVENT_TX_DSCR_ERR BIT(14)
42 #define I2S_LL_EVENT_TX_TEOF BIT(16)
43 #define I2S_INTR_MAX (UINT32_MAX)
44
45 #define I2S_LL_TX_EVENT_MASK I2S_LL_EVENT_TX_EOF
46 #define I2S_LL_RX_EVENT_MASK I2S_LL_EVENT_RX_EOF
47
48 #define I2S_LL_PLL_F160M_CLK_FREQ (160 * 1000000) // PLL_F160M_CLK: 160MHz
49 #define I2S_LL_DEFAULT_PLL_CLK_FREQ I2S_LL_PLL_F160M_CLK_FREQ // The default PLL clock frequency while using I2S_CLK_SRC_DEFAULT
50
51 /**
52 * @brief I2S clock configuration structure
53 * @note Fmclk = Fsclk /(integ+numer/denom)
54 */
55 typedef struct {
56 uint16_t integ; // Integer part of I2S module clock divider
57 uint16_t denom; // Denominator part of I2S module clock divider
58 uint16_t numer; // Numerator part of I2S module clock divider
59 } i2s_ll_mclk_div_t;
60
61 /**
62 * @brief Enable DMA descriptor owner check
63 *
64 * @param hw Peripheral I2S hardware instance address.
65 * @param en whether to enable owner check
66 */
i2s_ll_dma_enable_owner_check(i2s_dev_t * hw,bool en)67 static inline void i2s_ll_dma_enable_owner_check(i2s_dev_t *hw, bool en)
68 {
69 hw->lc_conf.check_owner = en;
70 }
71
72 /**
73 * @brief Enable DMA descriptor write back
74 *
75 * @param hw Peripheral I2S hardware instance address.
76 * @param en whether to enable write back
77 */
i2s_ll_dma_enable_auto_write_back(i2s_dev_t * hw,bool en)78 static inline void i2s_ll_dma_enable_auto_write_back(i2s_dev_t *hw, bool en)
79 {
80 hw->lc_conf.out_auto_wrback = en;
81 }
82
83 /**
84 * @brief I2S DMA generate EOF event on data in FIFO popped out
85 *
86 * @param hw Peripheral I2S hardware instance address.
87 * @param en True to enable, False to disable
88 */
i2s_ll_dma_enable_eof_on_fifo_empty(i2s_dev_t * hw,bool en)89 static inline void i2s_ll_dma_enable_eof_on_fifo_empty(i2s_dev_t *hw, bool en)
90 {
91 hw->lc_conf.out_eof_mode = en;
92 }
93
94 /**
95 * @brief I2S module general init, enable I2S clock.
96 *
97 * @param hw Peripheral I2S hardware instance address.
98 */
i2s_ll_enable_clock(i2s_dev_t * hw)99 static inline void i2s_ll_enable_clock(i2s_dev_t *hw)
100 {
101 if (hw->clkm_conf.clk_en == 0) {
102 hw->clkm_conf.clk_en = 1;
103 hw->conf2.val = 0;
104 }
105 }
106
107 /**
108 * @brief I2S module disable clock.
109 *
110 * @param hw Peripheral I2S hardware instance address.
111 */
i2s_ll_disable_clock(i2s_dev_t * hw)112 static inline void i2s_ll_disable_clock(i2s_dev_t *hw)
113 {
114 if (hw->clkm_conf.clk_en == 1) {
115 hw->clkm_conf.clk_en = 0;
116 }
117 }
118
119 /**
120 * @brief I2S tx msb right enable
121 *
122 * @param hw Peripheral I2S hardware instance address.
123 * @param enable Set true to enable tx msb right
124 */
i2s_ll_tx_enable_msb_right(i2s_dev_t * hw,bool enable)125 static inline void i2s_ll_tx_enable_msb_right(i2s_dev_t *hw, bool enable)
126 {
127 hw->conf.tx_msb_right = enable;
128 }
129
130 /**
131 * @brief I2S rx msb right enable
132 *
133 * @param hw Peripheral I2S hardware instance address.
134 * @param enable Set true to enable rx msb right
135 */
i2s_ll_rx_enable_msb_right(i2s_dev_t * hw,bool enable)136 static inline void i2s_ll_rx_enable_msb_right(i2s_dev_t *hw, bool enable)
137 {
138 hw->conf.rx_msb_right = enable;
139 }
140
141 /**
142 * @brief I2S tx right channel first
143 *
144 * @param hw Peripheral I2S hardware instance address.
145 * @param enable Set true to enable send right channel first
146 */
i2s_ll_tx_enable_right_first(i2s_dev_t * hw,bool enable)147 static inline void i2s_ll_tx_enable_right_first(i2s_dev_t *hw, bool enable)
148 {
149 hw->conf.tx_right_first = enable;
150 }
151
152 /**
153 * @brief I2S rx right channel first
154 *
155 * @param hw Peripheral I2S hardware instance address.
156 * @param enable Set true to enable receive right channel first
157 */
i2s_ll_rx_enable_right_first(i2s_dev_t * hw,bool enable)158 static inline void i2s_ll_rx_enable_right_first(i2s_dev_t *hw, bool enable)
159 {
160 hw->conf.rx_right_first = enable;
161 }
162
163 /**
164 * @brief I2S tx fifo module force enable
165 *
166 * @param hw Peripheral I2S hardware instance address.
167 * @param enable Set true to enable tx fifo module
168 */
i2s_ll_tx_force_enable_fifo_mod(i2s_dev_t * hw,bool enable)169 static inline void i2s_ll_tx_force_enable_fifo_mod(i2s_dev_t *hw, bool enable)
170 {
171 hw->fifo_conf.tx_fifo_mod_force_en = enable;
172 }
173
174 /**
175 * @brief I2S rx fifo module force enable
176 *
177 * @param hw Peripheral I2S hardware instance address.
178 * @param enable Set true to enable rx fifo module
179 */
i2s_ll_rx_force_enable_fifo_mod(i2s_dev_t * hw,bool enable)180 static inline void i2s_ll_rx_force_enable_fifo_mod(i2s_dev_t *hw, bool enable)
181 {
182 hw->fifo_conf.rx_fifo_mod_force_en = enable;
183 }
184 /**
185 * @brief Enable I2S TX slave mode
186 *
187 * @param hw Peripheral I2S hardware instance address.
188 * @param slave_en Set true to enable slave mode
189 */
i2s_ll_tx_set_slave_mod(i2s_dev_t * hw,bool slave_en)190 static inline void i2s_ll_tx_set_slave_mod(i2s_dev_t *hw, bool slave_en)
191 {
192 hw->conf.tx_slave_mod = slave_en;
193 }
194
195 /**
196 * @brief Enable I2S RX slave mode
197 *
198 * @param hw Peripheral I2S hardware instance address.
199 * @param slave_en Set true to enable slave mode
200 */
i2s_ll_rx_set_slave_mod(i2s_dev_t * hw,bool slave_en)201 static inline void i2s_ll_rx_set_slave_mod(i2s_dev_t *hw, bool slave_en)
202 {
203 hw->conf.rx_slave_mod = slave_en;
204 }
205
206 /**
207 * @brief Reset I2S TX module
208 *
209 * @param hw Peripheral I2S hardware instance address.
210 */
i2s_ll_tx_reset(i2s_dev_t * hw)211 static inline void i2s_ll_tx_reset(i2s_dev_t *hw)
212 {
213 hw->conf.tx_reset = 1;
214 hw->conf.tx_reset = 0;
215 hw->lc_conf.out_rst = 1;
216 hw->lc_conf.out_rst = 0;
217 }
218
219 /**
220 * @brief Reset I2S RX module
221 *
222 * @param hw Peripheral I2S hardware instance address.
223 */
i2s_ll_rx_reset(i2s_dev_t * hw)224 static inline void i2s_ll_rx_reset(i2s_dev_t *hw)
225 {
226 hw->conf.rx_reset = 1;
227 hw->conf.rx_reset = 0;
228 hw->lc_conf.in_rst = 1;
229 hw->lc_conf.in_rst = 0;
230 }
231
232 /**
233 * @brief Reset I2S TX FIFO
234 *
235 * @param hw Peripheral I2S hardware instance address.
236 */
i2s_ll_tx_reset_fifo(i2s_dev_t * hw)237 static inline void i2s_ll_tx_reset_fifo(i2s_dev_t *hw)
238 {
239 hw->conf.tx_fifo_reset = 1;
240 hw->conf.tx_fifo_reset = 0;
241 }
242
243 /**
244 * @brief Reset I2S RX FIFO
245 *
246 * @param hw Peripheral I2S hardware instance address.
247 */
i2s_ll_rx_reset_fifo(i2s_dev_t * hw)248 static inline void i2s_ll_rx_reset_fifo(i2s_dev_t *hw)
249 {
250 hw->conf.rx_fifo_reset = 1;
251 hw->conf.rx_fifo_reset = 0;
252 }
253
254 /**
255 * @brief Set TX source clock
256 *
257 * @param hw Peripheral I2S hardware instance address.
258 * @param src I2S source clock
259 */
i2s_ll_tx_clk_set_src(i2s_dev_t * hw,i2s_clock_src_t src)260 static inline void i2s_ll_tx_clk_set_src(i2s_dev_t *hw, i2s_clock_src_t src)
261 {
262 //0: disable APLL clock, I2S module will using PLL_D2_CLK(160M) as source clock
263 //1: Enable APLL clock, I2S module will using APLL as source clock
264 hw->clkm_conf.clka_en = (src == I2S_CLK_SRC_APLL) ? 1 : 0;
265 }
266
267 /**
268 * @brief Set RX source clock
269 *
270 * @param hw Peripheral I2S hardware instance address.
271 * @param src I2S source clock
272 */
i2s_ll_rx_clk_set_src(i2s_dev_t * hw,i2s_clock_src_t src)273 static inline void i2s_ll_rx_clk_set_src(i2s_dev_t *hw, i2s_clock_src_t src)
274 {
275 //0: disable APLL clock, I2S module will using PLL_D2_CLK(160M) as source clock
276 //1: Enable APLL clock, I2S module will using APLL as source clock
277 hw->clkm_conf.clka_en = (src == I2S_CLK_SRC_APLL) ? 1 : 0;
278 }
279
280 /**
281 * @brief Set I2S tx bck div num
282 *
283 * @param hw Peripheral I2S hardware instance address.
284 * @param val value to set tx bck div num
285 */
i2s_ll_tx_set_bck_div_num(i2s_dev_t * hw,uint32_t val)286 static inline void i2s_ll_tx_set_bck_div_num(i2s_dev_t *hw, uint32_t val)
287 {
288 hw->sample_rate_conf.tx_bck_div_num = val;
289 }
290
291 /**
292 * @brief Configure I2S module clock divider
293 * @note mclk on ESP32 is shared by both TX and RX channel
294 * mclk = sclk / (mclk_div + b/a)
295 *
296 * @param hw Peripheral I2S hardware instance address.
297 * @param mclk_div integer part of the division from sclk to mclk
298 * @param a Denominator of decimal part
299 * @param b Numerator of decimal part
300 */
i2s_ll_set_raw_mclk_div(i2s_dev_t * hw,uint32_t mclk_div,uint32_t a,uint32_t b)301 static inline void i2s_ll_set_raw_mclk_div(i2s_dev_t *hw, uint32_t mclk_div, uint32_t a, uint32_t b)
302 {
303 HAL_FORCE_MODIFY_U32_REG_FIELD(hw->clkm_conf, clkm_div_num, mclk_div);
304 hw->clkm_conf.clkm_div_b = b;
305 hw->clkm_conf.clkm_div_a = a;
306 }
307
308 /**
309 * @brief Configure I2S TX module clock divider
310 * @note mclk on ESP32 is shared by both TX and RX channel
311 *
312 * @param hw Peripheral I2S hardware instance address.
313 * @param mclk_div The mclk division coefficients
314 */
i2s_ll_tx_set_mclk(i2s_dev_t * hw,const i2s_ll_mclk_div_t * mclk_div)315 static inline void i2s_ll_tx_set_mclk(i2s_dev_t *hw, const i2s_ll_mclk_div_t *mclk_div)
316 {
317 i2s_ll_set_raw_mclk_div(hw, mclk_div->integ, mclk_div->denom, mclk_div->numer);
318 }
319
320 /**
321 * @brief Set I2S rx bck div num
322 *
323 * @param hw Peripheral I2S hardware instance address.
324 * @param val value to set rx bck div num
325 */
i2s_ll_rx_set_bck_div_num(i2s_dev_t * hw,uint32_t val)326 static inline void i2s_ll_rx_set_bck_div_num(i2s_dev_t *hw, uint32_t val)
327 {
328 hw->sample_rate_conf.rx_bck_div_num = val;
329 }
330
331 /**
332 * @brief Configure I2S RX module clock divider
333 * @note mclk on ESP32 is shared by both TX and RX channel
334 *
335 * @param hw Peripheral I2S hardware instance address.
336 * @param mclk_div The mclk division coefficients
337 */
i2s_ll_rx_set_mclk(i2s_dev_t * hw,const i2s_ll_mclk_div_t * mclk_div)338 static inline void i2s_ll_rx_set_mclk(i2s_dev_t *hw, const i2s_ll_mclk_div_t *mclk_div)
339 {
340 // TX and RX channel on ESP32 shares a same mclk
341 i2s_ll_tx_set_mclk(hw, mclk_div);
342 }
343
344 /**
345 * @brief Enable interrupt by mask
346 *
347 * @param hw Peripheral I2S hardware instance address.
348 * @param mask Interrupt event mask
349 * @param en true to enable, false to disable
350 */
i2s_ll_enable_intr(i2s_dev_t * hw,uint32_t mask,bool en)351 static inline void i2s_ll_enable_intr(i2s_dev_t *hw, uint32_t mask, bool en)
352 {
353 uint32_t int_ena_mask = hw->int_ena.val;
354 if (en) {
355 int_ena_mask |= mask;
356 } else {
357 int_ena_mask &= ~mask;
358 }
359 hw->int_ena.val = int_ena_mask;
360 }
361
362 /**
363 * @brief Enable TX interrupt
364 *
365 * @param hw Peripheral I2S hardware instance address.
366 */
i2s_ll_tx_enable_intr(i2s_dev_t * hw)367 static inline void i2s_ll_tx_enable_intr(i2s_dev_t *hw)
368 {
369 hw->int_ena.out_eof = 1;
370 }
371
372 /**
373 * @brief Disable TX interrupt
374 *
375 * @param hw Peripheral I2S hardware instance address.
376 */
i2s_ll_tx_disable_intr(i2s_dev_t * hw)377 static inline void i2s_ll_tx_disable_intr(i2s_dev_t *hw)
378 {
379 hw->int_ena.out_eof = 0;
380 }
381
382 /**
383 * @brief Enable RX interrupt
384 *
385 * @param hw Peripheral I2S hardware instance address.
386 */
i2s_ll_rx_enable_intr(i2s_dev_t * hw)387 static inline void i2s_ll_rx_enable_intr(i2s_dev_t *hw)
388 {
389 hw->int_ena.in_suc_eof = 1;
390 }
391
392 /**
393 * @brief Disable RX interrupt
394 *
395 * @param hw Peripheral I2S hardware instance address.
396 */
i2s_ll_rx_disable_intr(i2s_dev_t * hw)397 static inline void i2s_ll_rx_disable_intr(i2s_dev_t *hw)
398 {
399 hw->int_ena.in_suc_eof = 0;
400 }
401
402 /**
403 * @brief Get interrupt status register address
404 *
405 * @param hw Peripheral I2S hardware instance address.
406 * @return interrupt status register address
407 */
i2s_ll_get_intr_status_reg(i2s_dev_t * hw)408 static inline volatile void *i2s_ll_get_intr_status_reg(i2s_dev_t *hw)
409 {
410 return &hw->int_st;
411 }
412
413 /**
414 * @brief Get I2S interrupt status
415 *
416 * @param hw Peripheral I2S hardware instance address.
417 * @return
418 * - module interrupt status
419 */
420 __attribute__((always_inline))
i2s_ll_get_intr_status(i2s_dev_t * hw)421 static inline uint32_t i2s_ll_get_intr_status(i2s_dev_t *hw)
422 {
423 return hw->int_st.val;
424 }
425
426 /**
427 * @brief Get channel interrupt status register address
428 */
i2s_ll_get_interrupt_status_reg(i2s_dev_t * hw)429 static inline volatile void *i2s_ll_get_interrupt_status_reg(i2s_dev_t *hw)
430 {
431 return (volatile void *)(&hw->int_st);
432 }
433
434 /**
435 * @brief Clear I2S interrupt status
436 *
437 * @param hw Peripheral I2S hardware instance address.
438 * @param clr_mask Interrupt mask to clear interrupt status
439 */
440 __attribute__((always_inline))
i2s_ll_clear_intr_status(i2s_dev_t * hw,uint32_t clr_mask)441 static inline void i2s_ll_clear_intr_status(i2s_dev_t *hw, uint32_t clr_mask)
442 {
443 hw->int_clr.val = clr_mask;
444 }
445
446 /**
447 * @brief Reset dma out
448 *
449 * @param hw Peripheral I2S hardware instance address.
450 */
i2s_ll_tx_reset_dma(i2s_dev_t * hw)451 static inline void i2s_ll_tx_reset_dma(i2s_dev_t *hw)
452 {
453 hw->lc_conf.out_rst = 1;
454 hw->lc_conf.out_rst = 0;
455 }
456
457 /**
458 * @brief Reset dma in
459 *
460 * @param hw Peripheral I2S hardware instance address.
461 */
i2s_ll_rx_reset_dma(i2s_dev_t * hw)462 static inline void i2s_ll_rx_reset_dma(i2s_dev_t *hw)
463 {
464 hw->lc_conf.in_rst = 1;
465 hw->lc_conf.in_rst = 0;
466 }
467
468 /**
469 * @brief Start out link
470 *
471 * @param hw Peripheral I2S hardware instance address.
472 */
i2s_ll_start_out_link(i2s_dev_t * hw)473 static inline void i2s_ll_start_out_link(i2s_dev_t *hw)
474 {
475 hw->out_link.start = 1;
476 }
477
478 /**
479 * @brief Set I2S out link address
480 *
481 * @param hw Peripheral I2S hardware instance address.
482 * @param val value to set out link address
483 */
i2s_ll_set_out_link_addr(i2s_dev_t * hw,uint32_t val)484 static inline void i2s_ll_set_out_link_addr(i2s_dev_t *hw, uint32_t val)
485 {
486 hw->out_link.addr = val;
487 }
488
489 /**
490 * @brief Start TX module
491 *
492 * @param hw Peripheral I2S hardware instance address.
493 */
i2s_ll_tx_start(i2s_dev_t * hw)494 static inline void i2s_ll_tx_start(i2s_dev_t *hw)
495 {
496 hw->conf.tx_start = 1;
497 }
498
499 /**
500 * @brief Start RX module
501 *
502 * @param hw Peripheral I2S hardware instance address.
503 */
i2s_ll_rx_start(i2s_dev_t * hw)504 static inline void i2s_ll_rx_start(i2s_dev_t *hw)
505 {
506 hw->conf.rx_start = 1;
507 }
508
509 /**
510 * @brief Configure TX DMA descriptor address and start TX DMA
511 *
512 * @param hw Peripheral I2S hardware instance address.
513 * @param link_addr DMA descriptor link address.
514 */
i2s_ll_tx_start_link(i2s_dev_t * hw,uint32_t link_addr)515 static inline void i2s_ll_tx_start_link(i2s_dev_t *hw, uint32_t link_addr)
516 {
517 i2s_ll_set_out_link_addr(hw, link_addr);
518 i2s_ll_start_out_link(hw);
519 }
520
521 /**
522 * @brief Configure RX DMA descriptor address and start RX DMA
523 *
524 * @param hw Peripheral I2S hardware instance address.
525 * @param link_addr DMA descriptor link address.
526 */
i2s_ll_rx_start_link(i2s_dev_t * hw,uint32_t link_addr)527 static inline void i2s_ll_rx_start_link(i2s_dev_t *hw, uint32_t link_addr)
528 {
529 hw->in_link.addr = link_addr;
530 hw->in_link.start = 1;
531 }
532
533 /**
534 * @brief Stop TX module
535 *
536 * @param hw Peripheral I2S hardware instance address.
537 */
i2s_ll_tx_stop(i2s_dev_t * hw)538 static inline void i2s_ll_tx_stop(i2s_dev_t *hw)
539 {
540 hw->conf.tx_start = 0;
541 }
542
543 /**
544 * @brief Stop RX module
545 *
546 * @param hw Peripheral I2S hardware instance address.
547 */
i2s_ll_rx_stop(i2s_dev_t * hw)548 static inline void i2s_ll_rx_stop(i2s_dev_t *hw)
549 {
550 hw->conf.rx_start = 0;
551 }
552
553 /**
554 * @brief Stop out link
555 *
556 * @param hw Peripheral I2S hardware instance address.
557 */
i2s_ll_tx_stop_link(i2s_dev_t * hw)558 static inline void i2s_ll_tx_stop_link(i2s_dev_t *hw)
559 {
560 hw->out_link.stop = 1;
561 }
562
563 /**
564 * @brief Stop in link
565 *
566 * @param hw Peripheral I2S hardware instance address.
567 */
i2s_ll_rx_stop_link(i2s_dev_t * hw)568 static inline void i2s_ll_rx_stop_link(i2s_dev_t *hw)
569 {
570 hw->in_link.stop = 1;
571 }
572
573 /**
574 * @brief Get I2S out eof descriptor address
575 *
576 * @param hw Peripheral I2S hardware instance address.
577 * @param eof_addr Pointer to accept out eof des address
578 */
579 __attribute__((always_inline))
i2s_ll_tx_get_eof_des_addr(i2s_dev_t * hw,uint32_t * eof_addr)580 static inline void i2s_ll_tx_get_eof_des_addr(i2s_dev_t *hw, uint32_t *eof_addr)
581 {
582 *eof_addr = hw->out_eof_des_addr;
583 }
584
585 /**
586 * @brief Get I2S in eof descriptor address
587 *
588 * @param hw Peripheral I2S hardware instance address.
589 * @param eof_addr Pointer to accept in eof des address
590 */
591 __attribute__((always_inline))
i2s_ll_rx_get_eof_des_addr(i2s_dev_t * hw,uint32_t * eof_addr)592 static inline void i2s_ll_rx_get_eof_des_addr(i2s_dev_t *hw, uint32_t *eof_addr)
593 {
594 *eof_addr = hw->in_eof_des_addr;
595 }
596
597 /**
598 * @brief Configure the received length to trigger in_suc_eof interrupt
599 *
600 * @param hw Peripheral I2S hardware instance address.
601 * @param eof_num the byte length to trigger in_suc_eof interrupt
602 */
i2s_ll_rx_set_eof_num(i2s_dev_t * hw,int eof_num)603 static inline void i2s_ll_rx_set_eof_num(i2s_dev_t *hw, int eof_num)
604 {
605 // On ESP32, the eof_num count in words.
606 hw->rx_eof_num = eof_num / 4;
607 }
608
609 /**
610 * @brief Set I2S tx bits mod
611 *
612 * @param hw Peripheral I2S hardware instance address.
613 * @param val value to set tx bits mod
614 */
i2s_ll_tx_set_bits_mod(i2s_dev_t * hw,uint32_t val)615 static inline void i2s_ll_tx_set_bits_mod(i2s_dev_t *hw, uint32_t val)
616 {
617 hw->sample_rate_conf.tx_bits_mod = val;
618 }
619
620 /**
621 * @brief Configure TX chan bit and audio data bit, on ESP32, sample_bit should equals to data_bit
622 *
623 * @param hw Peripheral I2S hardware instance address.
624 * @param chan_bit The chan bit width
625 * @param data_bit The audio data bit width
626 */
i2s_ll_tx_set_sample_bit(i2s_dev_t * hw,uint8_t chan_bit,int data_bit)627 static inline void i2s_ll_tx_set_sample_bit(i2s_dev_t *hw, uint8_t chan_bit, int data_bit)
628 {
629 hw->fifo_conf.tx_fifo_mod = (chan_bit <= I2S_DATA_BIT_WIDTH_16BIT ? 0 : 2);
630 hw->sample_rate_conf.tx_bits_mod = data_bit;
631 }
632
633 /**
634 * @brief Configure RX chan bit and audio data bit, on ESP32, sample_bit should equals to data_bit
635 *
636 * @param hw Peripheral I2S hardware instance address.
637 * @param chan_bit The chan bit width
638 * @param data_bit The audio data bit width
639 */
i2s_ll_rx_set_sample_bit(i2s_dev_t * hw,uint8_t chan_bit,int data_bit)640 static inline void i2s_ll_rx_set_sample_bit(i2s_dev_t *hw, uint8_t chan_bit, int data_bit)
641 {
642 hw->fifo_conf.rx_fifo_mod = (chan_bit <= I2S_DATA_BIT_WIDTH_16BIT ? 0 : 2);
643 hw->sample_rate_conf.rx_bits_mod = data_bit;
644 }
645
646 /**
647 * @brief Set whether to continue I2S signal on bus when TX FIFO is empty
648 *
649 * @param hw Peripheral I2S hardware instance address.
650 * @param en whether to stop when tx fifo is empty
651 */
i2s_ll_tx_stop_on_fifo_empty(i2s_dev_t * hw,bool en)652 static inline void i2s_ll_tx_stop_on_fifo_empty(i2s_dev_t *hw, bool en)
653 {
654 hw->conf1.tx_stop_en = en;
655 }
656
657 /**
658 * @brief Set whether to bypass the internal PCM module
659 *
660 * @param hw Peripheral I2S hardware instance address.
661 * @param bypass whether to bypass the PCM module
662 */
i2s_ll_tx_bypass_pcm(i2s_dev_t * hw,bool bypass)663 static inline void i2s_ll_tx_bypass_pcm(i2s_dev_t *hw, bool bypass)
664 {
665 hw->conf1.tx_pcm_bypass = bypass;
666 }
667
668 /**
669 * @brief Enable I2S DMA
670 *
671 * @param hw Peripheral I2S hardware instance address.
672 * @param ena Set true to enable DMA
673 */
i2s_ll_enable_dma(i2s_dev_t * hw,bool ena)674 static inline void i2s_ll_enable_dma(i2s_dev_t *hw, bool ena)
675 {
676 hw->fifo_conf.dscr_en = ena;
677 }
678
679 /**
680 * @brief Configure TX WS signal width
681 *
682 * @param hw Peripheral I2S hardware instance address.
683 * @param width WS width in BCK cycle
684 */
i2s_ll_tx_set_ws_width(i2s_dev_t * hw,int width)685 static inline void i2s_ll_tx_set_ws_width(i2s_dev_t *hw, int width)
686 {
687 hw->conf.tx_short_sync = width == 1 ? 1 : 0;
688 }
689
690 /**
691 * @brief Configure RX WS signal width
692 *
693 * @param hw Peripheral I2S hardware instance address.
694 * @param width WS width in BCK cycle
695 */
i2s_ll_rx_set_ws_width(i2s_dev_t * hw,int width)696 static inline void i2s_ll_rx_set_ws_width(i2s_dev_t *hw, int width)
697 {
698 hw->conf.rx_short_sync = width == 1 ? 1 : 0;
699 }
700
701 /**
702 * @brief Enable TX MSB shift, the data will be launch at the first BCK clock
703 *
704 * @param hw Peripheral I2S hardware instance address.
705 * @param msb_shift_enable Set true to enable MSB shift
706 */
i2s_ll_tx_enable_msb_shift(i2s_dev_t * hw,bool msb_shift_enable)707 static inline void i2s_ll_tx_enable_msb_shift(i2s_dev_t *hw, bool msb_shift_enable)
708 {
709 hw->conf.tx_msb_shift = msb_shift_enable;
710 }
711
712 /**
713 * @brief Enable RX MSB shift, the data will be launch at the first BCK clock
714 *
715 * @param hw Peripheral I2S hardware instance address.
716 * @param msb_shift_enable Set true to enable MSB shift
717 */
i2s_ll_rx_enable_msb_shift(i2s_dev_t * hw,bool msb_shift_enable)718 static inline void i2s_ll_rx_enable_msb_shift(i2s_dev_t *hw, bool msb_shift_enable)
719 {
720 hw->conf.rx_msb_shift = msb_shift_enable;
721 }
722
723 /**
724 * @brief Set I2S PDM TX chan mode
725 * @param slot_mask select slot to send data
726 * @param is_mono is mono mode
727 */
i2s_ll_tx_select_pdm_slot(i2s_dev_t * hw,i2s_pdm_slot_mask_t slot_mask,bool is_mono)728 static inline void i2s_ll_tx_select_pdm_slot(i2s_dev_t *hw, i2s_pdm_slot_mask_t slot_mask, bool is_mono)
729 {
730 if (is_mono) {
731 switch (slot_mask)
732 {
733 case I2S_PDM_SLOT_RIGHT:
734 hw->conf_chan.tx_chan_mod = 3;
735 break;
736 case I2S_PDM_SLOT_LEFT:
737 hw->conf_chan.tx_chan_mod = 4;
738 break;
739 case I2S_PDM_SLOT_BOTH:
740 hw->conf_chan.tx_chan_mod = 1; // 1 & 2 has same effect
741 break;
742 default:
743 break;
744 }
745 } else {
746 switch (slot_mask)
747 {
748 case I2S_PDM_SLOT_RIGHT:
749 hw->conf_chan.tx_chan_mod = 1;
750 break;
751 case I2S_PDM_SLOT_LEFT:
752 hw->conf_chan.tx_chan_mod = 2;
753 break;
754 case I2S_PDM_SLOT_BOTH:
755 hw->conf_chan.tx_chan_mod = 0;
756 break;
757 default:
758 break;
759 }
760 }
761 }
762
763 /**
764 * @brief Set I2S PDM RX chan mode
765 * @param slot_mask select slot to send data
766 */
i2s_ll_rx_select_pdm_slot(i2s_dev_t * hw,i2s_pdm_slot_mask_t slot_mask)767 static inline void i2s_ll_rx_select_pdm_slot(i2s_dev_t *hw, i2s_pdm_slot_mask_t slot_mask)
768 {
769 switch (slot_mask)
770 {
771 case I2S_PDM_SLOT_RIGHT:
772 hw->conf_chan.rx_chan_mod = 1;
773 break;
774 case I2S_PDM_SLOT_LEFT:
775 hw->conf_chan.rx_chan_mod = 2;
776 break;
777 case I2S_PDM_SLOT_BOTH:
778 hw->conf_chan.rx_chan_mod = 0;
779 break;
780 default:
781 break;
782 }
783 }
784
785 /**
786 * @brief Set I2S tx chan mode
787 *
788 * @param hw Peripheral I2S hardware instance address.
789 * @param slot_mask select slot to send data
790 * @param is_mono is mono mode
791 */
i2s_ll_tx_select_std_slot(i2s_dev_t * hw,i2s_std_slot_mask_t slot_mask,bool is_mono)792 static inline void i2s_ll_tx_select_std_slot(i2s_dev_t *hw, i2s_std_slot_mask_t slot_mask, bool is_mono)
793 {
794 if (is_mono) {
795 switch (slot_mask)
796 {
797 case I2S_STD_SLOT_RIGHT:
798 hw->conf_chan.tx_chan_mod = 3;
799 break;
800 case I2S_STD_SLOT_LEFT:
801 hw->conf_chan.tx_chan_mod = 4;
802 break;
803 case I2S_STD_SLOT_BOTH:
804 hw->conf_chan.tx_chan_mod = 1; // 1 & 2 has same effect
805 break;
806 default:
807 break;
808 }
809 } else {
810 switch (slot_mask)
811 {
812 case I2S_STD_SLOT_RIGHT:
813 hw->conf_chan.tx_chan_mod = 1;
814 break;
815 case I2S_STD_SLOT_LEFT:
816 hw->conf_chan.tx_chan_mod = 2;
817 break;
818 case I2S_STD_SLOT_BOTH:
819 hw->conf_chan.tx_chan_mod = 0;
820 break;
821 default:
822 break;
823 }
824 }
825 }
826
827 /**
828 * @brief Set I2S rx chan mode
829 *
830 * @param hw Peripheral I2S hardware instance address.
831 * @param slot_mask select slot to receive data
832 * @param is_msb_right the slot sequence is affected by msb_right according to TRM
833 */
i2s_ll_rx_select_std_slot(i2s_dev_t * hw,i2s_std_slot_mask_t slot_mask,bool is_msb_right)834 static inline void i2s_ll_rx_select_std_slot(i2s_dev_t *hw, i2s_std_slot_mask_t slot_mask, bool is_msb_right)
835 {
836 switch (slot_mask)
837 {
838 case I2S_STD_SLOT_RIGHT:
839 hw->conf_chan.rx_chan_mod = is_msb_right ? 1 : 2;
840 break;
841 case I2S_STD_SLOT_LEFT:
842 hw->conf_chan.rx_chan_mod = is_msb_right ? 2 : 1;
843 break;
844 case I2S_STD_SLOT_BOTH:
845 hw->conf_chan.rx_chan_mod = 0;
846 break;
847 default:
848 break;
849 }
850 }
851
852 /**
853 * @brief Enable TX mono mode
854 *
855 * @param hw Peripheral I2S hardware instance address.
856 * @param mono_ena Set true to enable mono mde.
857 */
i2s_ll_tx_enable_mono_mode(i2s_dev_t * hw,bool mono_ena)858 static inline void i2s_ll_tx_enable_mono_mode(i2s_dev_t *hw, bool mono_ena)
859 {
860 int data_bit = hw->sample_rate_conf.tx_bits_mod;
861 hw->fifo_conf.tx_fifo_mod = data_bit <= I2S_DATA_BIT_WIDTH_16BIT ? mono_ena : 2 + mono_ena;
862 }
863
864 /**
865 * @brief Enable RX mono mode
866 *
867 * @param hw Peripheral I2S hardware instance address.
868 * @param mono_ena Set true to enable mono mde.
869 */
i2s_ll_rx_enable_mono_mode(i2s_dev_t * hw,bool mono_ena)870 static inline void i2s_ll_rx_enable_mono_mode(i2s_dev_t *hw, bool mono_ena)
871 {
872 int data_bit = hw->sample_rate_conf.rx_bits_mod;
873 hw->fifo_conf.rx_fifo_mod = data_bit <= I2S_DATA_BIT_WIDTH_16BIT ? mono_ena : 2 + mono_ena;
874 }
875
876 /**
877 * @brief Enable I2S loopback mode
878 *
879 * @param hw Peripheral I2S hardware instance address.
880 * @param loopback_en Set true to share BCK and WS signal for tx module and rx module.
881 */
i2s_ll_share_bck_ws(i2s_dev_t * hw,bool loopback_en)882 static inline void i2s_ll_share_bck_ws(i2s_dev_t *hw, bool loopback_en)
883 {
884 hw->conf.sig_loopback = loopback_en;
885 }
886
887
888
889 /******************************I2S PDM Configurations*************************************/
890 /**
891 * @brief Configure RX PDM downsample
892 *
893 * @param hw Peripheral I2S hardware instance address.
894 * @param dsr PDM downsample configuration paramater
895 */
i2s_ll_rx_set_pdm_dsr(i2s_dev_t * hw,i2s_pdm_dsr_t dsr)896 static inline void i2s_ll_rx_set_pdm_dsr(i2s_dev_t *hw, i2s_pdm_dsr_t dsr)
897 {
898 hw->pdm_conf.rx_sinc_dsr_16_en = dsr;
899 }
900
901 /**
902 * @brief Get RX PDM downsample configuration
903 *
904 * @param hw Peripheral I2S hardware instance address.
905 * @param dsr Pointer to accept PDM downsample configuration
906 */
i2s_ll_rx_get_pdm_dsr(i2s_dev_t * hw,i2s_pdm_dsr_t * dsr)907 static inline void i2s_ll_rx_get_pdm_dsr(i2s_dev_t *hw, i2s_pdm_dsr_t *dsr)
908 {
909 *dsr = (i2s_pdm_dsr_t)hw->pdm_conf.rx_sinc_dsr_16_en;
910 }
911
912 /**
913 * @brief Enable I2S TX STD mode
914 *
915 * @param hw Peripheral I2S hardware instance address.
916 */
i2s_ll_tx_enable_std(i2s_dev_t * hw)917 static inline void i2s_ll_tx_enable_std(i2s_dev_t *hw)
918 {
919 hw->conf2.val = 0;
920 hw->pdm_conf.tx_pdm_en = false;
921 hw->pdm_conf.pcm2pdm_conv_en = false;
922 }
923
924 /**
925 * @brief Enable I2S RX STD mode
926 *
927 * @param hw Peripheral I2S hardware instance address.
928 */
i2s_ll_rx_enable_std(i2s_dev_t * hw)929 static inline void i2s_ll_rx_enable_std(i2s_dev_t *hw)
930 {
931 hw->conf2.val = 0;
932 hw->pdm_conf.rx_pdm_en = false;
933 hw->pdm_conf.pdm2pcm_conv_en = false;
934 }
935
936 /**
937 * @brief Enable I2S TX PDM mode
938 *
939 * @param hw Peripheral I2S hardware instance address.
940 * @param pdm_ena Set true to enable TX PDM mode
941 */
i2s_ll_tx_enable_pdm(i2s_dev_t * hw)942 static inline void i2s_ll_tx_enable_pdm(i2s_dev_t *hw)
943 {
944 hw->conf2.val = 0;
945 hw->pdm_conf.tx_pdm_en = true;
946 hw->pdm_conf.pcm2pdm_conv_en = true;
947 }
948
949 /**
950 * @brief Enable I2S RX PDM mode
951 *
952 * @param hw Peripheral I2S hardware instance address.
953 */
i2s_ll_rx_enable_pdm(i2s_dev_t * hw)954 static inline void i2s_ll_rx_enable_pdm(i2s_dev_t *hw)
955 {
956 hw->conf2.val = 0;
957 hw->pdm_conf.rx_pdm_en = true;
958 hw->pdm_conf.pdm2pcm_conv_en = true;
959 }
960
961 /**
962 * @brief Set I2S TX PDM prescale
963 *
964 * @param hw Peripheral I2S hardware instance address.
965 * @param prescale I2S TX PDM prescale
966 */
i2s_ll_tx_set_pdm_prescale(i2s_dev_t * hw,bool prescale)967 static inline void i2s_ll_tx_set_pdm_prescale(i2s_dev_t *hw, bool prescale)
968 {
969 HAL_FORCE_MODIFY_U32_REG_FIELD(hw->pdm_conf, tx_prescale, prescale);
970 }
971
972 /**
973 * @brief Set I2S TX PDM high pass filter scaling
974 *
975 * @param hw Peripheral I2S hardware instance address.
976 * @param sig_scale I2S TX PDM signal scaling before transmit to the filter
977 */
i2s_ll_tx_set_pdm_hp_scale(i2s_dev_t * hw,i2s_pdm_sig_scale_t sig_scale)978 static inline void i2s_ll_tx_set_pdm_hp_scale(i2s_dev_t *hw, i2s_pdm_sig_scale_t sig_scale)
979 {
980 hw->pdm_conf.tx_hp_in_shift = sig_scale;
981 }
982
983 /**
984 * @brief Set I2S TX PDM low pass filter scaling
985 *
986 * @param hw Peripheral I2S hardware instance address.
987 * @param sig_scale I2S TX PDM signal scaling before transmit to the filter
988 */
i2s_ll_tx_set_pdm_lp_scale(i2s_dev_t * hw,i2s_pdm_sig_scale_t sig_scale)989 static inline void i2s_ll_tx_set_pdm_lp_scale(i2s_dev_t *hw, i2s_pdm_sig_scale_t sig_scale)
990 {
991 hw->pdm_conf.tx_lp_in_shift = sig_scale;
992 }
993
994 /**
995 * @brief Set I2S TX PDM sinc filter scaling
996 *
997 * @param hw Peripheral I2S hardware instance address.
998 * @param sig_scale I2S TX PDM signal scaling before transmit to the filter
999 */
i2s_ll_tx_set_pdm_sinc_scale(i2s_dev_t * hw,i2s_pdm_sig_scale_t sig_scale)1000 static inline void i2s_ll_tx_set_pdm_sinc_scale(i2s_dev_t *hw, i2s_pdm_sig_scale_t sig_scale)
1001 {
1002 hw->pdm_conf.tx_sinc_in_shift = sig_scale;
1003 }
1004
1005 /**
1006 * @brief Set I2S TX PDM sigma-delta filter scaling
1007 *
1008 * @param hw Peripheral I2S hardware instance address.
1009 * @param sig_scale I2S TX PDM signal scaling before transmit to the filter
1010 */
i2s_ll_tx_set_pdm_sd_scale(i2s_dev_t * hw,i2s_pdm_sig_scale_t sig_scale)1011 static inline void i2s_ll_tx_set_pdm_sd_scale(i2s_dev_t *hw, i2s_pdm_sig_scale_t sig_scale)
1012 {
1013 hw->pdm_conf.tx_sigmadelta_in_shift = sig_scale;
1014 }
1015
1016 /**
1017 * @brief Set the PDM TX over sampling ratio
1018 *
1019 * @param hw Peripheral I2S hardware instance address.
1020 * @param ovr Over sampling ratio
1021 */
i2s_ll_tx_set_pdm_over_sample_ratio(i2s_dev_t * hw,uint32_t ovr)1022 static inline void i2s_ll_tx_set_pdm_over_sample_ratio(i2s_dev_t *hw, uint32_t ovr)
1023 {
1024 hw->pdm_conf.tx_sinc_osr2 = ovr;
1025 }
1026
1027 /**
1028 * @brief Configure I2S TX PDM sample rate
1029 * Fpdm = 64*Fpcm*fp/fs
1030 *
1031 * @param hw Peripheral I2S hardware instance address.
1032 * @param fp The fp value of TX PDM filter module group0.
1033 * @param fs The fs value of TX PDM filter module group0.
1034 */
i2s_ll_tx_set_pdm_fpfs(i2s_dev_t * hw,uint32_t fp,uint32_t fs)1035 static inline void i2s_ll_tx_set_pdm_fpfs(i2s_dev_t *hw, uint32_t fp, uint32_t fs)
1036 {
1037 hw->pdm_freq_conf.tx_pdm_fp = fp;
1038 hw->pdm_freq_conf.tx_pdm_fs = fs;
1039 }
1040
1041 /**
1042 * @brief Get I2S TX PDM fp configuration paramater
1043 *
1044 * @param hw Peripheral I2S hardware instance address.
1045 * @return
1046 * - fp configuration paramater
1047 */
i2s_ll_tx_get_pdm_fp(i2s_dev_t * hw)1048 static inline uint32_t i2s_ll_tx_get_pdm_fp(i2s_dev_t *hw)
1049 {
1050 return hw->pdm_freq_conf.tx_pdm_fp;
1051 }
1052
1053 /**
1054 * @brief Get I2S TX PDM fs configuration paramater
1055 *
1056 * @param hw Peripheral I2S hardware instance address.
1057 * @return
1058 * - fs configuration paramater
1059 */
i2s_ll_tx_get_pdm_fs(i2s_dev_t * hw)1060 static inline uint32_t i2s_ll_tx_get_pdm_fs(i2s_dev_t *hw)
1061 {
1062 return hw->pdm_freq_conf.tx_pdm_fs;
1063 }
1064
1065
1066
1067
1068 /****************************I2S ADC/DAC Configurations***********************************/
1069 /**
1070 * @brief Enable I2S LCD mode
1071 * @note Have to enable LCD mode to use build in ADC/DAC
1072 *
1073 * @param hw Peripheral I2S hardware instance address.
1074 * @param enable Set true to enable LCD mode.
1075 */
i2s_ll_enable_lcd(i2s_dev_t * hw,bool enable)1076 static inline void i2s_ll_enable_lcd(i2s_dev_t *hw, bool enable)
1077 {
1078 hw->conf2.lcd_en = enable;
1079 }
1080
1081 /**
1082 * @brief Enable I2S camera mode
1083 *
1084 * @param hw Peripheral I2S hardware instance address.
1085 * @param enable Set true to enable camera mode.
1086 */
i2s_ll_enable_camera(i2s_dev_t * hw,bool enable)1087 static inline void i2s_ll_enable_camera(i2s_dev_t *hw, bool enable)
1088 {
1089 hw->conf2.camera_en = enable;
1090 }
1091
1092 /**
1093 * @brief Enable I2S build in ADC mode
1094 *
1095 * @param hw Peripheral I2S hardware instance address.
1096 * @param enable Set true to enable build in ADC
1097 */
i2s_ll_enable_builtin_adc(i2s_dev_t * hw,bool enable)1098 static inline void i2s_ll_enable_builtin_adc(i2s_dev_t *hw, bool enable)
1099 {
1100 hw->conf2.lcd_en = enable;
1101 hw->conf2.camera_en = 0;
1102 hw->conf.rx_right_first = 0;
1103 hw->conf.rx_msb_shift = 0;
1104 hw->conf.rx_mono = 0;
1105 hw->conf.rx_short_sync = 0;
1106 hw->fifo_conf.rx_fifo_mod = enable;
1107 hw->conf_chan.rx_chan_mod = enable;
1108 }
1109
1110 /**
1111 * @brief Enable I2S build in DAC mode
1112 *
1113 * @param hw Peripheral I2S hardware instance address.
1114 * * @param enable Set true to enable build in DAC
1115 */
i2s_ll_enable_builtin_dac(i2s_dev_t * hw,bool enable)1116 static inline void i2s_ll_enable_builtin_dac(i2s_dev_t *hw, bool enable)
1117 {
1118 hw->conf2.lcd_en = enable;
1119 hw->conf2.camera_en = 0;
1120 hw->conf.tx_right_first = enable;
1121 hw->conf.tx_msb_shift = 0;
1122 hw->conf.tx_short_sync = 0;
1123 }
1124
1125 #ifdef __cplusplus
1126 }
1127 #endif
1128