1 /*
2  * SPDX-FileCopyrightText: 2020-2023 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 poped 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     /* Workaround for inaccurate clock while switching from a relatively low sample rate to a high sample rate
318      * Set to particular coefficients first then update to the target coefficients,
319      * otherwise the clock division might be inaccurate.
320      * the general idea is to set a value that unlike to calculate from the regular decimal */
321     i2s_ll_set_raw_mclk_div(hw, 7, 47, 3);
322     i2s_ll_set_raw_mclk_div(hw, mclk_div->integ, mclk_div->denom, mclk_div->numer);
323 }
324 
325 /**
326  * @brief Set I2S rx bck div num
327  *
328  * @param hw Peripheral I2S hardware instance address.
329  * @param val value to set rx bck div num
330  */
i2s_ll_rx_set_bck_div_num(i2s_dev_t * hw,uint32_t val)331 static inline void i2s_ll_rx_set_bck_div_num(i2s_dev_t *hw, uint32_t val)
332 {
333     hw->sample_rate_conf.rx_bck_div_num = val;
334 }
335 
336 /**
337  * @brief Configure I2S RX module clock divider
338  * @note mclk on ESP32 is shared by both TX and RX channel
339  *
340  * @param hw Peripheral I2S hardware instance address.
341  * @param mclk_div The mclk division coefficients
342  */
i2s_ll_rx_set_mclk(i2s_dev_t * hw,const i2s_ll_mclk_div_t * mclk_div)343 static inline void i2s_ll_rx_set_mclk(i2s_dev_t *hw, const i2s_ll_mclk_div_t *mclk_div)
344 {
345     // TX and RX channel on ESP32 shares a same mclk
346     i2s_ll_tx_set_mclk(hw, mclk_div);
347 }
348 
349 /**
350  * @brief Enable interrupt by mask
351  *
352  * @param hw Peripheral I2S hardware instance address.
353  * @param mask Interrupt event mask
354  * @param en true to enable, false to disable
355  */
i2s_ll_enable_intr(i2s_dev_t * hw,uint32_t mask,bool en)356 static inline void i2s_ll_enable_intr(i2s_dev_t *hw, uint32_t mask, bool en)
357 {
358     uint32_t int_ena_mask = hw->int_ena.val;
359     if (en) {
360         int_ena_mask |= mask;
361     } else {
362         int_ena_mask &= ~mask;
363     }
364     hw->int_ena.val = int_ena_mask;
365 }
366 
367 /**
368  * @brief Enable TX interrupt
369  *
370  * @param hw Peripheral I2S hardware instance address.
371  */
i2s_ll_tx_enable_intr(i2s_dev_t * hw)372 static inline void i2s_ll_tx_enable_intr(i2s_dev_t *hw)
373 {
374     hw->int_ena.out_eof = 1;
375 }
376 
377 /**
378  * @brief Disable TX interrupt
379  *
380  * @param hw Peripheral I2S hardware instance address.
381  */
i2s_ll_tx_disable_intr(i2s_dev_t * hw)382 static inline void i2s_ll_tx_disable_intr(i2s_dev_t *hw)
383 {
384     hw->int_ena.out_eof = 0;
385 }
386 
387 /**
388  * @brief Enable RX interrupt
389  *
390  * @param hw Peripheral I2S hardware instance address.
391  */
i2s_ll_rx_enable_intr(i2s_dev_t * hw)392 static inline void i2s_ll_rx_enable_intr(i2s_dev_t *hw)
393 {
394     hw->int_ena.in_suc_eof = 1;
395 }
396 
397 /**
398  * @brief Disable RX interrupt
399  *
400  * @param hw Peripheral I2S hardware instance address.
401  */
i2s_ll_rx_disable_intr(i2s_dev_t * hw)402 static inline void i2s_ll_rx_disable_intr(i2s_dev_t *hw)
403 {
404     hw->int_ena.in_suc_eof = 0;
405 }
406 
407 /**
408  * @brief Get interrupt status register address
409  *
410  * @param hw Peripheral I2S hardware instance address.
411  * @return interrupt status register address
412  */
i2s_ll_get_intr_status_reg(i2s_dev_t * hw)413 static inline volatile void *i2s_ll_get_intr_status_reg(i2s_dev_t *hw)
414 {
415     return &hw->int_st;
416 }
417 
418 /**
419  * @brief Get I2S interrupt status
420  *
421  * @param hw Peripheral I2S hardware instance address.
422  * @return
423  *        - module interrupt status
424  */
425 __attribute__((always_inline))
i2s_ll_get_intr_status(i2s_dev_t * hw)426 static inline uint32_t i2s_ll_get_intr_status(i2s_dev_t *hw)
427 {
428     return hw->int_st.val;
429 }
430 
431 /**
432  * @brief Get channel interrupt status register address
433  */
i2s_ll_get_interrupt_status_reg(i2s_dev_t * hw)434 static inline volatile void *i2s_ll_get_interrupt_status_reg(i2s_dev_t *hw)
435 {
436     return (volatile void *)(&hw->int_st);
437 }
438 
439 /**
440  * @brief Clear I2S interrupt status
441  *
442  * @param hw Peripheral I2S hardware instance address.
443  * @param clr_mask Interrupt mask to clear interrupt status
444  */
445 __attribute__((always_inline))
i2s_ll_clear_intr_status(i2s_dev_t * hw,uint32_t clr_mask)446 static inline void i2s_ll_clear_intr_status(i2s_dev_t *hw, uint32_t clr_mask)
447 {
448     hw->int_clr.val = clr_mask;
449 }
450 
451 /**
452  * @brief Reset dma out
453  *
454  * @param hw Peripheral I2S hardware instance address.
455  */
i2s_ll_tx_reset_dma(i2s_dev_t * hw)456 static inline void i2s_ll_tx_reset_dma(i2s_dev_t *hw)
457 {
458     hw->lc_conf.out_rst = 1;
459     hw->lc_conf.out_rst = 0;
460 }
461 
462 /**
463  * @brief Reset dma in
464  *
465  * @param hw Peripheral I2S hardware instance address.
466  */
i2s_ll_rx_reset_dma(i2s_dev_t * hw)467 static inline void i2s_ll_rx_reset_dma(i2s_dev_t *hw)
468 {
469     hw->lc_conf.in_rst = 1;
470     hw->lc_conf.in_rst = 0;
471 }
472 
473 /**
474  * @brief Start out link
475  *
476  * @param hw Peripheral I2S hardware instance address.
477  */
i2s_ll_start_out_link(i2s_dev_t * hw)478 static inline void i2s_ll_start_out_link(i2s_dev_t *hw)
479 {
480     hw->out_link.start = 1;
481 }
482 
483 /**
484  * @brief Set I2S out link address
485  *
486  * @param hw Peripheral I2S hardware instance address.
487  * @param val value to set out link address
488  */
i2s_ll_set_out_link_addr(i2s_dev_t * hw,uint32_t val)489 static inline void i2s_ll_set_out_link_addr(i2s_dev_t *hw, uint32_t val)
490 {
491     hw->out_link.addr = val;
492 }
493 
494 /**
495  * @brief Start TX module
496  *
497  * @param hw Peripheral I2S hardware instance address.
498  */
i2s_ll_tx_start(i2s_dev_t * hw)499 static inline void i2s_ll_tx_start(i2s_dev_t *hw)
500 {
501     hw->conf.tx_start = 1;
502 }
503 
504 /**
505  * @brief Start RX module
506  *
507  * @param hw Peripheral I2S hardware instance address.
508  */
i2s_ll_rx_start(i2s_dev_t * hw)509 static inline void i2s_ll_rx_start(i2s_dev_t *hw)
510 {
511     hw->conf.rx_start = 1;
512 }
513 
514 /**
515  * @brief Configure TX DMA descriptor address and start TX DMA
516  *
517  * @param hw Peripheral I2S hardware instance address.
518  * @param link_addr DMA descriptor link address.
519  */
i2s_ll_tx_start_link(i2s_dev_t * hw,uint32_t link_addr)520 static inline void i2s_ll_tx_start_link(i2s_dev_t *hw, uint32_t link_addr)
521 {
522     i2s_ll_set_out_link_addr(hw, link_addr);
523     i2s_ll_start_out_link(hw);
524 }
525 
526 /**
527  * @brief Configure RX DMA descriptor address and start RX DMA
528  *
529  * @param hw Peripheral I2S hardware instance address.
530  * @param link_addr DMA descriptor link address.
531  */
i2s_ll_rx_start_link(i2s_dev_t * hw,uint32_t link_addr)532 static inline void i2s_ll_rx_start_link(i2s_dev_t *hw, uint32_t link_addr)
533 {
534     hw->in_link.addr = link_addr;
535     hw->in_link.start = 1;
536 }
537 
538 /**
539  * @brief Stop TX module
540  *
541  * @param hw Peripheral I2S hardware instance address.
542  */
i2s_ll_tx_stop(i2s_dev_t * hw)543 static inline void i2s_ll_tx_stop(i2s_dev_t *hw)
544 {
545     hw->conf.tx_start = 0;
546 }
547 
548 /**
549  * @brief Stop RX module
550  *
551  * @param hw Peripheral I2S hardware instance address.
552  */
i2s_ll_rx_stop(i2s_dev_t * hw)553 static inline void i2s_ll_rx_stop(i2s_dev_t *hw)
554 {
555     hw->conf.rx_start = 0;
556 }
557 
558 /**
559  * @brief Stop out link
560  *
561  * @param hw Peripheral I2S hardware instance address.
562  */
i2s_ll_tx_stop_link(i2s_dev_t * hw)563 static inline void i2s_ll_tx_stop_link(i2s_dev_t *hw)
564 {
565     hw->out_link.stop = 1;
566 }
567 
568 /**
569  * @brief Stop in link
570  *
571  * @param hw Peripheral I2S hardware instance address.
572  */
i2s_ll_rx_stop_link(i2s_dev_t * hw)573 static inline void i2s_ll_rx_stop_link(i2s_dev_t *hw)
574 {
575     hw->in_link.stop = 1;
576 }
577 
578 /**
579  * @brief Get I2S out eof descriptor address
580  *
581  * @param hw Peripheral I2S hardware instance address.
582  * @param eof_addr Pointer to accept out eof des address
583  */
584 __attribute__((always_inline))
i2s_ll_tx_get_eof_des_addr(i2s_dev_t * hw,uint32_t * eof_addr)585 static inline void i2s_ll_tx_get_eof_des_addr(i2s_dev_t *hw, uint32_t *eof_addr)
586 {
587     *eof_addr = hw->out_eof_des_addr;
588 }
589 
590 /**
591  * @brief Get I2S in eof descriptor address
592  *
593  * @param hw Peripheral I2S hardware instance address.
594  * @param eof_addr Pointer to accept in eof des address
595  */
596 __attribute__((always_inline))
i2s_ll_rx_get_eof_des_addr(i2s_dev_t * hw,uint32_t * eof_addr)597 static inline void i2s_ll_rx_get_eof_des_addr(i2s_dev_t *hw, uint32_t *eof_addr)
598 {
599     *eof_addr = hw->in_eof_des_addr;
600 }
601 
602 /**
603  * @brief Configure the received length to trigger in_suc_eof interrupt
604  *
605  * @param hw Peripheral I2S hardware instance address.
606  * @param eof_num the byte length to trigger in_suc_eof interrupt
607  */
i2s_ll_rx_set_eof_num(i2s_dev_t * hw,int eof_num)608 static inline void i2s_ll_rx_set_eof_num(i2s_dev_t *hw, int eof_num)
609 {
610     // On ESP32, the eof_num count in words.
611     hw->rx_eof_num = eof_num / 4;
612 }
613 
614 /**
615  * @brief Set I2S tx bits mod
616  *
617  * @param hw Peripheral I2S hardware instance address.
618  * @param val value to set tx bits mod
619  */
i2s_ll_tx_set_bits_mod(i2s_dev_t * hw,uint32_t val)620 static inline void i2s_ll_tx_set_bits_mod(i2s_dev_t *hw, uint32_t val)
621 {
622     hw->sample_rate_conf.tx_bits_mod = val;
623 }
624 
625 /**
626  * @brief Congfigure TX chan bit and audio data bit, on ESP32, sample_bit should equals to data_bit
627  *
628  * @param hw Peripheral I2S hardware instance address.
629  * @param chan_bit The chan bit width
630  * @param data_bit The audio data bit width
631  */
i2s_ll_tx_set_sample_bit(i2s_dev_t * hw,uint8_t chan_bit,int data_bit)632 static inline void i2s_ll_tx_set_sample_bit(i2s_dev_t *hw, uint8_t chan_bit, int data_bit)
633 {
634     hw->fifo_conf.tx_fifo_mod = (chan_bit <= I2S_DATA_BIT_WIDTH_16BIT ? 0 : 2);
635     hw->sample_rate_conf.tx_bits_mod = data_bit;
636 }
637 
638 /**
639  * @brief Congfigure RX chan bit and audio data bit, on ESP32, sample_bit should equals to data_bit
640  *
641  * @param hw Peripheral I2S hardware instance address.
642  * @param chan_bit The chan bit width
643  * @param data_bit The audio data bit width
644  */
i2s_ll_rx_set_sample_bit(i2s_dev_t * hw,uint8_t chan_bit,int data_bit)645 static inline void i2s_ll_rx_set_sample_bit(i2s_dev_t *hw, uint8_t chan_bit, int data_bit)
646 {
647     hw->fifo_conf.rx_fifo_mod = (chan_bit <= I2S_DATA_BIT_WIDTH_16BIT ? 0 : 2);
648     hw->sample_rate_conf.rx_bits_mod = data_bit;
649 }
650 
651 /**
652  * @brief Set whether to continue I2S signal on bus when TX FIFO is empty
653  *
654  * @param hw Peripheral I2S hardware instance address.
655  * @param en whether to stop when tx fifo is empty
656  */
i2s_ll_tx_stop_on_fifo_empty(i2s_dev_t * hw,bool en)657 static inline void i2s_ll_tx_stop_on_fifo_empty(i2s_dev_t *hw, bool en)
658 {
659     hw->conf1.tx_stop_en = en;
660 }
661 
662 /**
663  * @brief Set whether to bypass the internal PCM module
664  *
665  * @param hw Peripheral I2S hardware instance address.
666  * @param bypass whether to bypass the PCM module
667  */
i2s_ll_tx_bypass_pcm(i2s_dev_t * hw,bool bypass)668 static inline void i2s_ll_tx_bypass_pcm(i2s_dev_t *hw, bool bypass)
669 {
670     hw->conf1.tx_pcm_bypass = bypass;
671 }
672 
673 /**
674  * @brief Enable I2S DMA
675  *
676  * @param hw Peripheral I2S hardware instance address.
677  * @param ena Set true to enable DMA
678  */
i2s_ll_enable_dma(i2s_dev_t * hw,bool ena)679 static inline void i2s_ll_enable_dma(i2s_dev_t *hw, bool ena)
680 {
681     hw->fifo_conf.dscr_en = ena;
682 }
683 
684 /**
685  * @brief Configure TX WS signal width
686  *
687  * @param hw Peripheral I2S hardware instance address.
688  * @param width WS width in BCK cycle
689  */
i2s_ll_tx_set_ws_width(i2s_dev_t * hw,int width)690 static inline void i2s_ll_tx_set_ws_width(i2s_dev_t *hw, int width)
691 {
692     hw->conf.tx_short_sync = width == 1 ? 1 : 0;
693 }
694 
695 /**
696  * @brief Configure RX WS signal width
697  *
698  * @param hw Peripheral I2S hardware instance address.
699  * @param width WS width in BCK cycle
700  */
i2s_ll_rx_set_ws_width(i2s_dev_t * hw,int width)701 static inline void i2s_ll_rx_set_ws_width(i2s_dev_t *hw, int width)
702 {
703     hw->conf.rx_short_sync = width == 1 ? 1 : 0;
704 }
705 
706 /**
707  * @brief Enable TX MSB shift, the data will be launch at the first BCK clock
708  *
709  * @param hw Peripheral I2S hardware instance address.
710  * @param msb_shift_enable Set true to enable MSB shift
711  */
i2s_ll_tx_enable_msb_shift(i2s_dev_t * hw,bool msb_shift_enable)712 static inline void i2s_ll_tx_enable_msb_shift(i2s_dev_t *hw, bool msb_shift_enable)
713 {
714     hw->conf.tx_msb_shift = msb_shift_enable;
715 }
716 
717 /**
718  * @brief Enable RX MSB shift, the data will be launch at the first BCK clock
719  *
720  * @param hw Peripheral I2S hardware instance address.
721  * @param msb_shift_enable Set true to enable MSB shift
722  */
i2s_ll_rx_enable_msb_shift(i2s_dev_t * hw,bool msb_shift_enable)723 static inline void i2s_ll_rx_enable_msb_shift(i2s_dev_t *hw, bool msb_shift_enable)
724 {
725     hw->conf.rx_msb_shift = msb_shift_enable;
726 }
727 
728 /**
729  * @brief Set I2S PDM TX chan mode
730  * @param slot_mask select slot to send data
731  * @param is_mono is mono mode
732  */
i2s_ll_tx_select_pdm_slot(i2s_dev_t * hw,i2s_pdm_slot_mask_t slot_mask,bool is_mono)733 static inline void i2s_ll_tx_select_pdm_slot(i2s_dev_t *hw, i2s_pdm_slot_mask_t slot_mask, bool is_mono)
734 {
735     if (is_mono) {
736         switch (slot_mask)
737         {
738         case I2S_PDM_SLOT_RIGHT:
739             hw->conf_chan.tx_chan_mod = 3;
740             break;
741         case I2S_PDM_SLOT_LEFT:
742             hw->conf_chan.tx_chan_mod = 4;
743             break;
744         case I2S_PDM_SLOT_BOTH:
745             hw->conf_chan.tx_chan_mod = 1; // 1 & 2 has same effect
746             break;
747         default:
748             break;
749         }
750     } else {
751         switch (slot_mask)
752         {
753         case I2S_PDM_SLOT_RIGHT:
754             hw->conf_chan.tx_chan_mod = 1;
755             break;
756         case I2S_PDM_SLOT_LEFT:
757             hw->conf_chan.tx_chan_mod = 2;
758             break;
759         case I2S_PDM_SLOT_BOTH:
760             hw->conf_chan.tx_chan_mod = 0;
761             break;
762         default:
763             break;
764         }
765     }
766 }
767 
768 /**
769  * @brief Set I2S PDM RX chan mode
770  * @param slot_mask select slot to send data
771  */
i2s_ll_rx_select_pdm_slot(i2s_dev_t * hw,i2s_pdm_slot_mask_t slot_mask)772 static inline void i2s_ll_rx_select_pdm_slot(i2s_dev_t *hw, i2s_pdm_slot_mask_t slot_mask)
773 {
774     switch (slot_mask)
775     {
776     case I2S_PDM_SLOT_RIGHT:
777         hw->conf_chan.rx_chan_mod = 1;
778         break;
779     case I2S_PDM_SLOT_LEFT:
780         hw->conf_chan.rx_chan_mod = 2;
781         break;
782     case I2S_PDM_SLOT_BOTH:
783         hw->conf_chan.rx_chan_mod = 0;
784         break;
785     default:
786         break;
787     }
788 }
789 
790 /**
791  * @brief Set I2S tx chan mode
792  *
793  * @param hw Peripheral I2S hardware instance address.
794  * @param slot_mask select slot to send data
795  * @param is_mono is mono mode
796  */
i2s_ll_tx_select_std_slot(i2s_dev_t * hw,i2s_std_slot_mask_t slot_mask,bool is_mono)797 static inline void i2s_ll_tx_select_std_slot(i2s_dev_t *hw, i2s_std_slot_mask_t slot_mask, bool is_mono)
798 {
799     if (is_mono) {
800         switch (slot_mask)
801         {
802         case I2S_STD_SLOT_RIGHT:
803             hw->conf_chan.tx_chan_mod = 3;
804             break;
805         case I2S_STD_SLOT_LEFT:
806             hw->conf_chan.tx_chan_mod = 4;
807             break;
808         case I2S_STD_SLOT_BOTH:
809             hw->conf_chan.tx_chan_mod = 1; // 1 & 2 has same effect
810             break;
811         default:
812             break;
813         }
814     } else {
815         switch (slot_mask)
816         {
817         case I2S_STD_SLOT_RIGHT:
818             hw->conf_chan.tx_chan_mod = 1;
819             break;
820         case I2S_STD_SLOT_LEFT:
821             hw->conf_chan.tx_chan_mod = 2;
822             break;
823         case I2S_STD_SLOT_BOTH:
824             hw->conf_chan.tx_chan_mod = 0;
825             break;
826         default:
827             break;
828         }
829     }
830 }
831 
832 /**
833  * @brief Set I2S rx chan mode
834  *
835  * @param hw Peripheral I2S hardware instance address.
836  * @param slot_mask select slot to receive data
837  * @param is_msb_right the slot sequence is affected by msb_right according to TRM
838  */
i2s_ll_rx_select_std_slot(i2s_dev_t * hw,i2s_std_slot_mask_t slot_mask,bool is_msb_right)839 static inline void i2s_ll_rx_select_std_slot(i2s_dev_t *hw, i2s_std_slot_mask_t slot_mask, bool is_msb_right)
840 {
841     switch (slot_mask)
842     {
843     case I2S_STD_SLOT_RIGHT:
844         hw->conf_chan.rx_chan_mod = is_msb_right ? 1 : 2;
845         break;
846     case I2S_STD_SLOT_LEFT:
847         hw->conf_chan.rx_chan_mod = is_msb_right ? 2 : 1;
848         break;
849     case I2S_STD_SLOT_BOTH:
850         hw->conf_chan.rx_chan_mod = 0;
851         break;
852     default:
853         break;
854     }
855 }
856 
857 /**
858  * @brief Enable TX mono mode
859  *
860  * @param hw Peripheral I2S hardware instance address.
861  * @param mono_ena Set true to enable mono mde.
862  */
i2s_ll_tx_enable_mono_mode(i2s_dev_t * hw,bool mono_ena)863 static inline void i2s_ll_tx_enable_mono_mode(i2s_dev_t *hw, bool mono_ena)
864 {
865     int data_bit = hw->sample_rate_conf.tx_bits_mod;
866     hw->fifo_conf.tx_fifo_mod = data_bit <= I2S_DATA_BIT_WIDTH_16BIT ? mono_ena : 2 + mono_ena;
867 }
868 
869 /**
870  * @brief Enable RX mono mode
871  *
872  * @param hw Peripheral I2S hardware instance address.
873  * @param mono_ena Set true to enable mono mde.
874  */
i2s_ll_rx_enable_mono_mode(i2s_dev_t * hw,bool mono_ena)875 static inline void i2s_ll_rx_enable_mono_mode(i2s_dev_t *hw, bool mono_ena)
876 {
877     int data_bit = hw->sample_rate_conf.rx_bits_mod;
878     hw->fifo_conf.rx_fifo_mod = data_bit <= I2S_DATA_BIT_WIDTH_16BIT ? mono_ena : 2 + mono_ena;
879 }
880 
881 /**
882  * @brief Enable I2S loopback mode
883  *
884  * @param hw Peripheral I2S hardware instance address.
885  * @param loopback_en Set true to share BCK and WS signal for tx module and rx module.
886  */
i2s_ll_share_bck_ws(i2s_dev_t * hw,bool loopback_en)887 static inline void i2s_ll_share_bck_ws(i2s_dev_t *hw, bool loopback_en)
888 {
889     hw->conf.sig_loopback = loopback_en;
890 }
891 
892 
893 
894 /******************************I2S PDM Configurations*************************************/
895 /**
896  * @brief Configure RX PDM downsample
897  *
898  * @param hw Peripheral I2S hardware instance address.
899  * @param dsr PDM downsample configuration paramater
900  */
i2s_ll_rx_set_pdm_dsr(i2s_dev_t * hw,i2s_pdm_dsr_t dsr)901 static inline void i2s_ll_rx_set_pdm_dsr(i2s_dev_t *hw, i2s_pdm_dsr_t dsr)
902 {
903     hw->pdm_conf.rx_sinc_dsr_16_en = dsr;
904 }
905 
906 /**
907  * @brief Get RX PDM downsample configuration
908  *
909  * @param hw Peripheral I2S hardware instance address.
910  * @param dsr Pointer to accept PDM downsample configuration
911  */
i2s_ll_rx_get_pdm_dsr(i2s_dev_t * hw,i2s_pdm_dsr_t * dsr)912 static inline void i2s_ll_rx_get_pdm_dsr(i2s_dev_t *hw, i2s_pdm_dsr_t *dsr)
913 {
914     *dsr = (i2s_pdm_dsr_t)hw->pdm_conf.rx_sinc_dsr_16_en;
915 }
916 
917 /**
918  * @brief Enable I2S TX STD mode
919  *
920  * @param hw Peripheral I2S hardware instance address.
921  */
i2s_ll_tx_enable_std(i2s_dev_t * hw)922 static inline void i2s_ll_tx_enable_std(i2s_dev_t *hw)
923 {
924     hw->conf2.val = 0;
925     hw->pdm_conf.tx_pdm_en = false;
926     hw->pdm_conf.pcm2pdm_conv_en = false;
927 }
928 
929 /**
930  * @brief Enable I2S RX STD mode
931  *
932  * @param hw Peripheral I2S hardware instance address.
933  */
i2s_ll_rx_enable_std(i2s_dev_t * hw)934 static inline void i2s_ll_rx_enable_std(i2s_dev_t *hw)
935 {
936     hw->conf2.val = 0;
937     hw->pdm_conf.rx_pdm_en = false;
938     hw->pdm_conf.pdm2pcm_conv_en = false;
939 }
940 
941 /**
942  * @brief Enable I2S TX PDM mode
943  *
944  * @param hw Peripheral I2S hardware instance address.
945  * @param pdm_ena Set true to enable TX PDM mode
946  */
i2s_ll_tx_enable_pdm(i2s_dev_t * hw)947 static inline void i2s_ll_tx_enable_pdm(i2s_dev_t *hw)
948 {
949     hw->conf2.val = 0;
950     hw->pdm_conf.tx_pdm_en = true;
951     hw->pdm_conf.pcm2pdm_conv_en = true;
952 }
953 
954 /**
955  * @brief Enable I2S RX PDM mode
956  *
957  * @param hw Peripheral I2S hardware instance address.
958  */
i2s_ll_rx_enable_pdm(i2s_dev_t * hw)959 static inline void i2s_ll_rx_enable_pdm(i2s_dev_t *hw)
960 {
961     hw->conf2.val = 0;
962     hw->pdm_conf.rx_pdm_en = true;
963     hw->pdm_conf.pdm2pcm_conv_en = true;
964 }
965 
966 /**
967  * @brief Set I2S TX PDM prescale
968  *
969  * @param hw Peripheral I2S hardware instance address.
970  * @param prescale I2S TX PDM prescale
971  */
i2s_ll_tx_set_pdm_prescale(i2s_dev_t * hw,bool prescale)972 static inline void i2s_ll_tx_set_pdm_prescale(i2s_dev_t *hw, bool prescale)
973 {
974     HAL_FORCE_MODIFY_U32_REG_FIELD(hw->pdm_conf, tx_prescale, prescale);
975 }
976 
977 /**
978  * @brief Set I2S TX PDM high pass filter scaling
979  *
980  * @param hw Peripheral I2S hardware instance address.
981  * @param sig_scale I2S TX PDM signal scaling before transmit to the filter
982  */
i2s_ll_tx_set_pdm_hp_scale(i2s_dev_t * hw,i2s_pdm_sig_scale_t sig_scale)983 static inline void i2s_ll_tx_set_pdm_hp_scale(i2s_dev_t *hw, i2s_pdm_sig_scale_t sig_scale)
984 {
985     hw->pdm_conf.tx_hp_in_shift = sig_scale;
986 }
987 
988 /**
989  * @brief Set I2S TX PDM low pass filter scaling
990  *
991  * @param hw Peripheral I2S hardware instance address.
992  * @param sig_scale I2S TX PDM signal scaling before transmit to the filter
993  */
i2s_ll_tx_set_pdm_lp_scale(i2s_dev_t * hw,i2s_pdm_sig_scale_t sig_scale)994 static inline void i2s_ll_tx_set_pdm_lp_scale(i2s_dev_t *hw, i2s_pdm_sig_scale_t sig_scale)
995 {
996     hw->pdm_conf.tx_lp_in_shift = sig_scale;
997 }
998 
999 /**
1000  * @brief Set I2S TX PDM sinc filter scaling
1001  *
1002  * @param hw Peripheral I2S hardware instance address.
1003  * @param sig_scale I2S TX PDM signal scaling before transmit to the filter
1004  */
i2s_ll_tx_set_pdm_sinc_scale(i2s_dev_t * hw,i2s_pdm_sig_scale_t sig_scale)1005 static inline void i2s_ll_tx_set_pdm_sinc_scale(i2s_dev_t *hw, i2s_pdm_sig_scale_t sig_scale)
1006 {
1007     hw->pdm_conf.tx_sinc_in_shift = sig_scale;
1008 }
1009 
1010 /**
1011  * @brief Set I2S TX PDM sigma-delta filter scaling
1012  *
1013  * @param hw Peripheral I2S hardware instance address.
1014  * @param sig_scale I2S TX PDM signal scaling before transmit to the filter
1015  */
i2s_ll_tx_set_pdm_sd_scale(i2s_dev_t * hw,i2s_pdm_sig_scale_t sig_scale)1016 static inline void i2s_ll_tx_set_pdm_sd_scale(i2s_dev_t *hw, i2s_pdm_sig_scale_t sig_scale)
1017 {
1018     hw->pdm_conf.tx_sigmadelta_in_shift = sig_scale;
1019 }
1020 
1021 /**
1022  * @brief Set the PDM TX over sampling ratio
1023  *
1024  * @param hw  Peripheral I2S hardware instance address.
1025  * @param ovr Over sampling ratio
1026  */
i2s_ll_tx_set_pdm_over_sample_ratio(i2s_dev_t * hw,uint32_t ovr)1027 static inline void i2s_ll_tx_set_pdm_over_sample_ratio(i2s_dev_t *hw, uint32_t ovr)
1028 {
1029     hw->pdm_conf.tx_sinc_osr2 = ovr;
1030 }
1031 
1032 /**
1033  * @brief Configure I2S TX PDM sample rate
1034  *        Fpdm = 64*Fpcm*fp/fs
1035  *
1036  * @param hw Peripheral I2S hardware instance address.
1037  * @param fp The fp value of TX PDM filter module group0.
1038  * @param fs The fs value of TX PDM filter module group0.
1039  */
i2s_ll_tx_set_pdm_fpfs(i2s_dev_t * hw,uint32_t fp,uint32_t fs)1040 static inline void i2s_ll_tx_set_pdm_fpfs(i2s_dev_t *hw, uint32_t fp, uint32_t fs)
1041 {
1042     hw->pdm_freq_conf.tx_pdm_fp = fp;
1043     hw->pdm_freq_conf.tx_pdm_fs = fs;
1044 }
1045 
1046 /**
1047  * @brief Get I2S TX PDM fp configuration paramater
1048  *
1049  * @param hw Peripheral I2S hardware instance address.
1050  * @return
1051  *        - fp configuration paramater
1052  */
i2s_ll_tx_get_pdm_fp(i2s_dev_t * hw)1053 static inline uint32_t i2s_ll_tx_get_pdm_fp(i2s_dev_t *hw)
1054 {
1055     return hw->pdm_freq_conf.tx_pdm_fp;
1056 }
1057 
1058 /**
1059  * @brief Get I2S TX PDM fs configuration paramater
1060  *
1061  * @param hw Peripheral I2S hardware instance address.
1062  * @return
1063  *        - fs configuration paramater
1064  */
i2s_ll_tx_get_pdm_fs(i2s_dev_t * hw)1065 static inline uint32_t i2s_ll_tx_get_pdm_fs(i2s_dev_t *hw)
1066 {
1067     return hw->pdm_freq_conf.tx_pdm_fs;
1068 }
1069 
1070 
1071 
1072 
1073 /****************************I2S ADC/DAC Configurations***********************************/
1074 /**
1075  * @brief Enable I2S LCD mode
1076  * @note  Have to enable LCD mode to use build in ADC/DAC
1077  *
1078  * @param hw Peripheral I2S hardware instance address.
1079  * @param enable Set true to enable LCD mode.
1080  */
i2s_ll_enable_lcd(i2s_dev_t * hw,bool enable)1081 static inline void i2s_ll_enable_lcd(i2s_dev_t *hw, bool enable)
1082 {
1083     hw->conf2.lcd_en = enable;
1084 }
1085 
1086 /**
1087  * @brief Enable I2S camera mode
1088  *
1089  * @param hw Peripheral I2S hardware instance address.
1090  * @param enable Set true to enable camera mode.
1091  */
i2s_ll_enable_camera(i2s_dev_t * hw,bool enable)1092 static inline void i2s_ll_enable_camera(i2s_dev_t *hw, bool enable)
1093 {
1094     hw->conf2.camera_en = enable;
1095 }
1096 
1097 /**
1098  * @brief Enable I2S build in ADC mode
1099  *
1100  * @param hw Peripheral I2S hardware instance address.
1101  * @param enable Set true to enable build in ADC
1102  */
i2s_ll_enable_builtin_adc(i2s_dev_t * hw,bool enable)1103 static inline void i2s_ll_enable_builtin_adc(i2s_dev_t *hw, bool enable)
1104 {
1105     hw->conf2.lcd_en = enable;
1106     hw->conf2.camera_en = 0;
1107     hw->conf.rx_right_first = 0;
1108     hw->conf.rx_msb_shift = 0;
1109     hw->conf.rx_mono = 0;
1110     hw->conf.rx_short_sync = 0;
1111     hw->fifo_conf.rx_fifo_mod = enable;
1112     hw->conf_chan.rx_chan_mod = enable;
1113 }
1114 
1115 /**
1116  * @brief Enable I2S build in DAC mode
1117  *
1118  * @param hw Peripheral I2S hardware instance address.
1119  *  * @param enable Set true to enable build in DAC
1120  */
i2s_ll_enable_builtin_dac(i2s_dev_t * hw,bool enable)1121 static inline void i2s_ll_enable_builtin_dac(i2s_dev_t *hw, bool enable)
1122 {
1123     hw->conf2.lcd_en = enable;
1124     hw->conf2.camera_en = 0;
1125     hw->conf.tx_right_first = enable;
1126     hw->conf.tx_msb_shift = 0;
1127     hw->conf.tx_short_sync = 0;
1128 }
1129 
1130 #ifdef __cplusplus
1131 }
1132 #endif
1133