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 HAL layer for I2S.
14 // There is no parameter check in the hal layer, so the caller must ensure the correctness of the parameters.
15 
16 #pragma once
17 
18 #include "soc/soc_caps.h"
19 #include "hal/i2s_types.h"
20 #include "hal/i2s_ll.h"
21 
22 #ifdef __cplusplus
23 extern "C" {
24 #endif
25 
26 /**
27  * @brief General slot configuration information
28  * @note It is a general purpose struct, not supposed to be used directly by user
29  */
30 typedef struct {
31     i2s_data_bit_width_t    data_bit_width;     /*!< I2S sample data bit width (valid data bits per sample) */
32     i2s_slot_bit_width_t    slot_bit_width;     /*!< I2S slot bit width (total bits per slot) */
33     i2s_slot_mode_t         slot_mode;          /*!< Set mono or stereo mode with I2S_SLOT_MODE_MONO or I2S_SLOT_MODE_STEREO */
34     union {
35         /* STD configurations */
36         struct {
37             i2s_std_slot_mask_t     slot_mask;          /*!< Select the left, right or both slot */
38             uint32_t                ws_width;           /*!< WS signal width (i.e. the number of bclk ticks that ws signal is high) */
39             bool                    ws_pol;             /*!< WS signal polarity, set true to enable high lever first */
40             bool                    bit_shift;          /*!< Set to enbale bit shift in Philips mode */
41 #if SOC_I2S_HW_VERSION_1    // For esp32/esp32-s2
42             bool                    msb_right;          /*!< Set to place right channel data at the MSB in the FIFO */
43 #else
44             bool                    left_align;         /*!< Set to enable left alignment */
45             bool                    big_endian;         /*!< Set to enable big endian */
46             bool                    bit_order_lsb;      /*!< Set to enable lsb first */
47 #endif
48         } std;                                          /*!< Specific configurations for standard mode */
49 
50 #if SOC_I2S_SUPPORTS_TDM
51         /* TDM configurations */
52         struct {
53             i2s_tdm_slot_mask_t     slot_mask;          /*!< Slot mask. Activating slots by setting 1 to corresponding bits. When the activated slots is not consecutive, those data in unactivated slots will be ignored */
54             uint32_t                ws_width;           /*!< WS signal width ((i.e. the number of bclk ticks that ws signal is high)) */
55             bool                    ws_pol;             /*!< WS signal polarity, set true to enable high lever first */
56             bool                    bit_shift;          /*!< Set true to enable bit shift in Philips mode */
57 
58             bool                    left_align;         /*!< Set true to enable left alignment */
59             bool                    big_endian;         /*!< Set true to enable big endian */
60             bool                    bit_order_lsb;      /*!< Set true to enable lsb first */
61 
62             bool                    skip_mask;          /*!< Set true to enable skip mask. If it is enabled, only the data of the enabled channels will be sent, otherwise all data stored in DMA TX buffer will be sent */
63             uint32_t                total_slot;         /*!< I2S total number of slots. If it is smaller than the biggest activated channel number, it will be set to this number automatically. */
64         } tdm;                                          /*!< Specific configurations for TDM mode */
65 #endif
66 
67 #if SOC_I2S_SUPPORTS_PDM_TX
68         /* PDM TX configurations */
69         struct {
70 #if SOC_I2S_HW_VERSION_1
71             i2s_pdm_slot_mask_t     slot_mask;          /*!< Slot mask to choose left or right slot */
72 #endif
73             uint32_t                sd_prescale;        /*!< Sigma-delta filter prescale */
74             i2s_pdm_sig_scale_t     sd_scale;           /*!< Sigma-delta filter scaling value */
75             i2s_pdm_sig_scale_t     hp_scale;           /*!< High pass filter scaling value */
76             i2s_pdm_sig_scale_t     lp_scale;           /*!< Low pass filter scaling value */
77             i2s_pdm_sig_scale_t     sinc_scale;         /*!< Sinc filter scaling value */
78 #if SOC_I2S_HW_VERSION_2
79             i2s_pdm_tx_line_mode_t  line_mode;          /*!< PDM TX line mode, on-line codec, one-line dac, two-line dac mode can be selected */
80             bool                    hp_en;              /*!< High pass filter enable */
81             float                   hp_cut_off_freq_hz; /*!< High pass filter cut-off frequency, range 23.3Hz ~ 185Hz, see cut-off frequency sheet above */
82             uint32_t                sd_dither;          /*!< Sigma-delta filter dither */
83             uint32_t                sd_dither2;         /*!< Sigma-delta filter dither2 */
84 #endif // SOC_I2S_HW_VERSION_2
85         } pdm_tx;                                       /*!< Specific configurations for PDM TX mode */
86 #endif
87 #if SOC_I2S_SUPPORTS_PDM_RX
88         /* PDM TX configurations */
89         struct {
90             i2s_pdm_slot_mask_t     slot_mask;          /*!< Choose the slots to activate */
91         } pdm_rx;                                       /*!< Specific configurations for PDM TX mode */
92 #endif
93     };
94 
95 } i2s_hal_slot_config_t;
96 
97 /**
98  * @brief I2S clock configuration
99  */
100 typedef struct {
101     uint32_t sclk;                              /*!< I2S module clock */
102     uint32_t mclk;                              /*!< I2S master clock */
103     uint32_t bclk;                              /*!< I2S bit clock */
104     uint16_t mclk_div;                          /*!< I2S master clock division */
105     uint16_t bclk_div;                          /*!< I2S bit clock division*/
106 } i2s_hal_clock_info_t;
107 
108 /**
109  * Context that should be maintained by both the driver and the HAL
110  */
111 typedef struct {
112     i2s_dev_t *dev;                             /*!< I2S instance address */
113 } i2s_hal_context_t;
114 
115 /**
116  * @brief Init I2S hal context
117  *
118  * @param hal Context of the HAL layer
119  * @param port_id The I2S port number, the max port number is (SOC_I2S_NUM -1)
120  */
121 void i2s_hal_init(i2s_hal_context_t *hal, int port_id);
122 
123 /**
124  * @brief Helper function for calculating the precise mclk division by sclk and mclk
125  *
126  * @param sclk      system clock
127  * @param mclk      module clock
128  * @param mclk_div  mclk division coefficients, including integer part and decimal part
129  */
130 void i2s_hal_calc_mclk_precise_division(uint32_t sclk, uint32_t mclk, i2s_ll_mclk_div_t *mclk_div);
131 
132 /**
133  * @brief Set tx channel clock
134  *
135  * @param hal Context of the HAL layer
136  * @param clk_info clock information
137  * @param clk_src clock source
138  */
139 void i2s_hal_set_tx_clock(i2s_hal_context_t *hal, const i2s_hal_clock_info_t *clk_info, i2s_clock_src_t clk_src);
140 
141 /**
142  * @brief Set rx channel clock
143  *
144  * @param hal Context of the HAL layer
145  * @param clk_info clock information
146  * @param clk_src clock source
147  */
148 void i2s_hal_set_rx_clock(i2s_hal_context_t *hal, const i2s_hal_clock_info_t *clk_info, i2s_clock_src_t clk_src);
149 
150 
151 /*-------------------------------------------------------------------------
152  |                           STD configuration                            |
153  -------------------------------------------------------------------------*/
154 /**
155  * @brief Set tx slot to standard mode
156  *
157  * @param hal Context of the HAL layer
158  * @param is_slave If is slave role
159  * @param slot_config General slot configuration pointer, but will specified to i2s standard mode
160  */
161 void i2s_hal_std_set_tx_slot(i2s_hal_context_t *hal, bool is_slave, const i2s_hal_slot_config_t *slot_cfg);
162 
163 /**
164  * @brief Set rx slot to standard mode
165  *
166  * @param hal Context of the HAL layer
167  * @param is_slave If is slave role
168  * @param slot_config General slot configuration pointer, but will specified to i2s standard mode
169  */
170 void i2s_hal_std_set_rx_slot(i2s_hal_context_t *hal, bool is_slave, const i2s_hal_slot_config_t *slot_cfg);
171 
172 /**
173  * @brief Enable tx channel as standard mode
174  *
175  * @param hal Context of the HAL layer
176  */
177 void i2s_hal_std_enable_tx_channel(i2s_hal_context_t *hal);
178 
179 /**
180  * @brief Enable rx channel as standard mode
181  *
182  * @param hal Context of the HAL layer
183  */
184 void i2s_hal_std_enable_rx_channel(i2s_hal_context_t *hal);
185 
186 /*-------------------------------------------------------------------------
187  |                           PDM configuration                            |
188  -------------------------------------------------------------------------*/
189 #if SOC_I2S_SUPPORTS_PDM
190 
191 #if SOC_I2S_SUPPORTS_PDM_TX
192 /**
193  * @brief Set tx slot to pdm mode
194  *
195  * @param hal Context of the HAL layer
196  * @param is_slave If is slave role
197  * @param slot_config General slot configuration pointer, but will specified to i2s pdm tx mode
198  */
199 void i2s_hal_pdm_set_tx_slot(i2s_hal_context_t *hal, bool is_slave, const i2s_hal_slot_config_t *slot_cfg);
200 
201 /**
202  * @brief Enable tx channel as pdm mode
203  *
204  * @param hal Context of the HAL layer
205  */
206 void i2s_hal_pdm_enable_tx_channel(i2s_hal_context_t *hal);
207 #endif // SOC_I2S_SUPPORTS_PDM_TX
208 
209 #if SOC_I2S_SUPPORTS_PDM_RX
210 /**
211  * @brief Set rx slot to pdm mode
212  *
213  * @param hal Context of the HAL layer
214  * @param is_slave If is slave role
215  * @param slot_config General slot configuration pointer, but will specified to i2s pdm rx mode
216  */
217 void i2s_hal_pdm_set_rx_slot(i2s_hal_context_t *hal, bool is_slave, const i2s_hal_slot_config_t *slot_cfg);
218 
219 /**
220  * @brief Enable rx channel as pdm mode
221  *
222  * @param hal Context of the HAL layer
223  */
224 void i2s_hal_pdm_enable_rx_channel(i2s_hal_context_t *hal);
225 #endif // SOC_I2S_SUPPORTS_PDM_RX
226 #endif // SOC_I2S_SUPPORTS_PDM
227 
228 /*-------------------------------------------------------------------------
229  |                           TDM configuration                            |
230  -------------------------------------------------------------------------*/
231 #if SOC_I2S_SUPPORTS_TDM
232 /**
233  * @brief Set tx slot to tdm mode
234  *
235  * @param hal Context of the HAL layer
236  * @param is_slave If is slave role
237  * @param slot_config General slot configuration pointer, but will specified to i2s tdm mode
238  */
239 void i2s_hal_tdm_set_tx_slot(i2s_hal_context_t *hal, bool is_slave, const i2s_hal_slot_config_t *slot_cfg);
240 
241 /**
242  * @brief Set rx slot to tdm mode
243  *
244  * @param hal Context of the HAL layer
245  * @param is_slave If is slave role
246  * @param slot_config General slot configuration pointer, but will specified to i2s tdm mode
247  */
248 void i2s_hal_tdm_set_rx_slot(i2s_hal_context_t *hal, bool is_slave, const i2s_hal_slot_config_t *slot_cfg);
249 
250 /**
251  * @brief Enable tx channel as tdm mode
252  *
253  * @param hal Context of the HAL layer
254  */
255 void i2s_hal_tdm_enable_tx_channel(i2s_hal_context_t *hal);
256 
257 /**
258  * @brief Enable rx channel as tdm mode
259  *
260  * @param hal Context of the HAL layer
261  */
262 void i2s_hal_tdm_enable_rx_channel(i2s_hal_context_t *hal);
263 #endif
264 
265 /**
266  * @brief Start I2S TX channel
267  *
268  * @param hal Context of the HAL layer
269  */
270 #define i2s_hal_tx_start(hal)                   i2s_ll_tx_start((hal)->dev)
271 
272 /**
273  * @brief Stop I2S TX channel
274  *
275  * @param hal Context of the HAL layer
276  */
277 #define i2s_hal_tx_stop(hal)                   i2s_ll_tx_stop((hal)->dev)
278 
279 /**
280  * @brief Reset I2S TX channel
281  *
282  * @param hal Context of the HAL layer
283  */
284 #define i2s_hal_tx_reset(hal)                   i2s_ll_tx_reset((hal)->dev)
285 
286 /**
287  * @brief Reset I2S TX fifo
288  *
289  * @param hal Context of the HAL layer
290  */
291 #define i2s_hal_tx_reset_fifo(hal)              i2s_ll_tx_reset_fifo((hal)->dev)
292 
293 /**
294  * @brief Start I2S RX channel
295  *
296  * @param hal Context of the HAL layer
297  */
298 #define i2s_hal_rx_start(hal)                   i2s_ll_rx_start((hal)->dev)
299 
300 /**
301  * @brief Stop I2S RX channel
302  *
303  * @param hal Context of the HAL layer
304  */
305 #define i2s_hal_rx_stop(hal)                   i2s_ll_rx_stop((hal)->dev)
306 
307 /**
308  * @brief Reset I2S RX channel
309  *
310  * @param hal Context of the HAL layer
311  */
312 #define i2s_hal_rx_reset(hal)                   i2s_ll_rx_reset((hal)->dev)
313 
314 /**
315  * @brief Reset I2S RX fifo
316  *
317  * @param hal Context of the HAL layer
318  */
319 #define i2s_hal_rx_reset_fifo(hal)              i2s_ll_rx_reset_fifo((hal)->dev)
320 
321 
322 #if !SOC_I2S_SUPPORTS_GDMA
323 /**
324  * @brief Enable I2S TX DMA
325  *
326  * @param hal Context of the HAL layer
327  */
328 #define i2s_hal_tx_enable_dma(hal) i2s_ll_enable_dma((hal)->dev,true)
329 
330 /**
331  * @brief Enable I2S RX DMA
332  *
333  * @param hal Context of the HAL layer
334  */
335 #define i2s_hal_rx_enable_dma(hal) i2s_ll_enable_dma((hal)->dev,true)
336 
337 /**
338  * @brief Disable I2S TX DMA
339  *
340  * @param hal Context of the HAL layer
341  */
342 #define i2s_hal_tx_disable_dma(hal) i2s_ll_enable_dma((hal)->dev,false)
343 
344 /**
345  * @brief Disable I2S RX DMA
346  *
347  * @param hal Context of the HAL layer
348  */
349 #define i2s_hal_rx_disable_dma(hal) i2s_ll_enable_dma((hal)->dev,false)
350 
351 /**
352  * @brief Get I2S interrupt status
353  *
354  * @param hal Context of the HAL layer
355  * @return
356  *        - module interrupt status
357  */
358 #define i2s_hal_get_intr_status(hal) i2s_ll_get_intr_status((hal)->dev)
359 
360 /**
361  * @brief Get I2S interrupt status
362  *
363  * @param hal Context of the HAL layer
364  * @param mask Interrupt mask to be cleared.
365  */
366 #define i2s_hal_clear_intr_status(hal, mask) i2s_ll_clear_intr_status((hal)->dev, mask)
367 
368 /**
369  * @brief Enable I2S RX interrupt
370  *
371  * @param hal Context of the HAL layer
372  */
373 #define i2s_hal_rx_enable_intr(hal) i2s_ll_rx_enable_intr((hal)->dev)
374 
375 /**
376  * @brief Disable I2S RX interrupt
377  *
378  * @param hal Context of the HAL layer
379  */
380 #define i2s_hal_rx_disable_intr(hal) i2s_ll_rx_disable_intr((hal)->dev)
381 
382 /**
383  * @brief Disable I2S TX interrupt
384  *
385  * @param hal Context of the HAL layer
386  */
387 #define i2s_hal_tx_disable_intr(hal) i2s_ll_tx_disable_intr((hal)->dev)
388 
389 /**
390  * @brief Enable I2S TX interrupt
391  *
392  * @param hal Context of the HAL layer
393  */
394 #define i2s_hal_tx_enable_intr(hal) i2s_ll_tx_enable_intr((hal)->dev)
395 
396 /**
397  * @brief Configure TX DMA descriptor address and start TX DMA
398  *
399  * @param hal Context of the HAL layer
400  * @param link_addr DMA descriptor link address.
401  */
402 #define i2s_hal_tx_start_link(hal, link_addr) i2s_ll_tx_start_link((hal)->dev, link_addr)
403 
404 /**
405  * @brief Configure RX DMA descriptor address and start RX DMA
406  *
407  * @param hal Context of the HAL layer
408  * @param link_addr DMA descriptor link address.
409  */
410 #define i2s_hal_rx_start_link(hal, link_addr) i2s_ll_rx_start_link((hal)->dev, link_addr)
411 
412 /**
413  * @brief Stop TX DMA link
414  *
415  * @param hal Context of the HAL layer
416  */
417 #define i2s_hal_tx_stop_link(hal) i2s_ll_tx_stop_link((hal)->dev)
418 
419 /**
420  * @brief Stop RX DMA link
421  *
422  * @param hal Context of the HAL layer
423  */
424 #define i2s_hal_rx_stop_link(hal) i2s_ll_rx_stop_link((hal)->dev)
425 
426 /**
427  * @brief Reset RX DMA
428  *
429  * @param hal Context of the HAL layer
430  */
431 #define i2s_hal_rx_reset_dma(hal) i2s_ll_rx_reset_dma((hal)->dev)
432 
433 /**
434  * @brief Reset TX DMA
435  *
436  * @param hal Context of the HAL layer
437  */
438 #define i2s_hal_tx_reset_dma(hal) i2s_ll_tx_reset_dma((hal)->dev)
439 
440 /**
441  * @brief Get I2S out eof descriptor address
442  *
443  * @param hal Context of the HAL layer
444  * @param addr Pointer to accept out eof des address
445  */
446 #define i2s_hal_get_out_eof_des_addr(hal, addr) i2s_ll_tx_get_eof_des_addr((hal)->dev, addr)
447 
448 /**
449  * @brief Get I2S in suc eof descriptor address
450  *
451  * @param hal Context of the HAL layer
452  * @param addr Pointer to accept in suc eof des address
453  */
454 #define i2s_hal_get_in_eof_des_addr(hal, addr) i2s_ll_rx_get_eof_des_addr((hal)->dev, addr)
455 #endif
456 
457 #ifdef __cplusplus
458 }
459 #endif
460