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