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