diff --git a/components/driver/i2s.c b/components/driver/i2s.c index 2cb466344..129c81002 100644 --- a/components/driver/i2s.c +++ b/components/driver/i2s.c @@ -3,7 +3,7 @@ // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at - +// // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software @@ -11,22 +11,19 @@ // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. + #include +#include #include #include #include "freertos/FreeRTOS.h" #include "freertos/queue.h" #include "freertos/xtensa_api.h" -#include "soc/i2s_periph.h" -#include "soc/rtc_periph.h" -#include "soc/rtc.h" -#include "soc/efuse_periph.h" -#include "esp32/rom/lldesc.h" +#include "esp32/rom/lldesc.h" #include "driver/gpio.h" #include "driver/i2s.h" -#include "driver/rtc_io.h" #include "driver/dac.h" #include "adc1_i2s_private.h" @@ -34,8 +31,6 @@ #include "esp_err.h" #include "esp_log.h" #include "esp_pm.h" -#include "sdkconfig.h" - static const char* I2S_TAG = "I2S"; @@ -43,19 +38,14 @@ static const char* I2S_TAG = "I2S"; ESP_LOGE(I2S_TAG,"%s:%d (%s):%s", __FILE__, __LINE__, __FUNCTION__, str); \ return (ret); \ } -#define I2S_MAX_BUFFER_SIZE (4 * 1024 * 1024) //the maximum RAM can be allocated -#define I2S_BASE_CLK (2*APB_CLK_FREQ) + #define I2S_ENTER_CRITICAL_ISR() portENTER_CRITICAL_ISR(&i2s_spinlock[i2s_num]) #define I2S_EXIT_CRITICAL_ISR() portEXIT_CRITICAL_ISR(&i2s_spinlock[i2s_num]) #define I2S_ENTER_CRITICAL() portENTER_CRITICAL(&i2s_spinlock[i2s_num]) #define I2S_EXIT_CRITICAL() portEXIT_CRITICAL(&i2s_spinlock[i2s_num]) #define I2S_FULL_DUPLEX_SLAVE_MODE_MASK (I2S_MODE_TX | I2S_MODE_RX | I2S_MODE_SLAVE) #define I2S_FULL_DUPLEX_MASTER_MODE_MASK (I2S_MODE_TX | I2S_MODE_RX | I2S_MODE_MASTER) -#define APLL_MIN_FREQ (250000000) -#define APLL_MAX_FREQ (500000000) -#define APLL_I2S_MIN_RATE (10675) //in Hz, I2S Clock rate limited by hardware -#define I2S_AD_BCK_FACTOR (2) -#define I2S_PDM_BCK_FACTOR (64) + /** * @brief DMA buffer object * @@ -95,29 +85,23 @@ typedef struct { #ifdef CONFIG_PM_ENABLE esp_pm_lock_handle_t pm_lock; #endif + i2s_hal_context_t hal; /*!< I2S hal context*/ } i2s_obj_t; static i2s_obj_t *p_i2s_obj[I2S_NUM_MAX] = {0}; -#ifdef CONFIG_IDF_TARGET_ESP32 -static i2s_dev_t* I2S[I2S_NUM_MAX] = {&I2S0, &I2S1}; -static portMUX_TYPE i2s_spinlock[I2S_NUM_MAX] = {portMUX_INITIALIZER_UNLOCKED,portMUX_INITIALIZER_UNLOCKED}; -#elif defined CONFIG_IDF_TARGET_ESP32S2BETA -static i2s_dev_t* I2S[I2S_NUM_MAX] = {&I2S0}; -static portMUX_TYPE i2s_spinlock[I2S_NUM_MAX] = {portMUX_INITIALIZER_UNLOCKED}; -#endif + +static portMUX_TYPE i2s_spinlock[I2S_NUM_MAX]; static int _i2s_adc_unit = -1; static int _i2s_adc_channel = -1; static i2s_dma_t *i2s_create_dma_queue(i2s_port_t i2s_num, int dma_buf_count, int dma_buf_len); static esp_err_t i2s_destroy_dma_queue(i2s_port_t i2s_num, i2s_dma_t *dma); + static esp_err_t i2s_reset_fifo(i2s_port_t i2s_num) { I2S_CHECK((i2s_num < I2S_NUM_MAX), "i2s_num error", ESP_ERR_INVALID_ARG); I2S_ENTER_CRITICAL(); - I2S[i2s_num]->conf.rx_fifo_reset = 1; - I2S[i2s_num]->conf.rx_fifo_reset = 0; - I2S[i2s_num]->conf.tx_fifo_reset = 1; - I2S[i2s_num]->conf.tx_fifo_reset = 0; + i2s_hal_reset_fifo(&(p_i2s_obj[i2s_num]->hal)); I2S_EXIT_CRITICAL(); return ESP_OK; } @@ -131,6 +115,7 @@ inline static void gpio_matrix_out_check(uint32_t gpio, uint32_t signal_idx, boo gpio_matrix_out(gpio, signal_idx, out_inv, oen_inv); } } + inline static void gpio_matrix_in_check(uint32_t gpio, uint32_t signal_idx, bool inv) { if (gpio != -1) { @@ -141,11 +126,10 @@ inline static void gpio_matrix_in_check(uint32_t gpio, uint32_t signal_idx, bool } } - esp_err_t i2s_clear_intr_status(i2s_port_t i2s_num, uint32_t clr_mask) { I2S_CHECK((i2s_num < I2S_NUM_MAX), "i2s_num error", ESP_ERR_INVALID_ARG); - I2S[i2s_num]->int_clr.val = clr_mask; + i2s_hal_clear_intr_status(&(p_i2s_obj[i2s_num]->hal), clr_mask); return ESP_OK; } @@ -153,8 +137,7 @@ esp_err_t i2s_enable_rx_intr(i2s_port_t i2s_num) { I2S_ENTER_CRITICAL(); - I2S[i2s_num]->int_ena.in_suc_eof = 1; - I2S[i2s_num]->int_ena.in_dscr_err = 1; + i2s_hal_enable_rx_intr(&(p_i2s_obj[i2s_num]->hal)); I2S_EXIT_CRITICAL(); return ESP_OK; } @@ -162,8 +145,7 @@ esp_err_t i2s_enable_rx_intr(i2s_port_t i2s_num) esp_err_t i2s_disable_rx_intr(i2s_port_t i2s_num) { I2S_ENTER_CRITICAL(); - I2S[i2s_num]->int_ena.in_suc_eof = 0; - I2S[i2s_num]->int_ena.in_dscr_err = 0; + i2s_hal_disable_rx_intr(&(p_i2s_obj[i2s_num]->hal)); I2S_EXIT_CRITICAL(); return ESP_OK; } @@ -171,8 +153,7 @@ esp_err_t i2s_disable_rx_intr(i2s_port_t i2s_num) esp_err_t i2s_disable_tx_intr(i2s_port_t i2s_num) { I2S_ENTER_CRITICAL(); - I2S[i2s_num]->int_ena.out_eof = 0; - I2S[i2s_num]->int_ena.out_dscr_err = 0; + i2s_hal_disable_tx_intr(&(p_i2s_obj[i2s_num]->hal)); I2S_EXIT_CRITICAL(); return ESP_OK; } @@ -180,8 +161,7 @@ esp_err_t i2s_disable_tx_intr(i2s_port_t i2s_num) esp_err_t i2s_enable_tx_intr(i2s_port_t i2s_num) { I2S_ENTER_CRITICAL(); - I2S[i2s_num]->int_ena.out_eof = 1; - I2S[i2s_num]->int_ena.out_dscr_err = 1; + i2s_hal_enable_tx_intr(&(p_i2s_obj[i2s_num]->hal)); I2S_EXIT_CRITICAL(); return ESP_OK; } @@ -197,20 +177,15 @@ static esp_err_t i2s_isr_register(i2s_port_t i2s_num, int intr_alloc_flags, void return esp_intr_alloc(i2s_periph_signal[i2s_num].irq, intr_alloc_flags, fn, arg, handle); } - static float i2s_apll_get_fi2s(int bits_per_sample, int sdm0, int sdm1, int sdm2, int odir) { int f_xtal = (int)rtc_clk_xtal_freq_get() * 1000000; -#ifdef CONFIG_IDF_TARGET_ESP32 - uint32_t is_rev0 = (GET_PERI_REG_BITS2(EFUSE_BLK0_RDATA3_REG, 1, 15) == 0); - if (is_rev0) { + uint32_t rev; + i2s_hal_get_rev(&(p_i2s_obj[0]->hal), &rev); // I2S hardware instance address will not be used + if (rev) { sdm0 = 0; sdm1 = 0; } -#elif defined CONFIG_IDF_TARGET_ESP32S2BETA - sdm0 = 0; - sdm1 = 0; -#endif float fout = f_xtal * (sdm2 + sdm1 / 256.0f + sdm0 / 65536.0f + 4); if (fout < APLL_MIN_FREQ || fout > APLL_MAX_FREQ) { return APLL_MAX_FREQ; @@ -320,6 +295,7 @@ static esp_err_t i2s_apll_calculate_fi2s(int rate, int bits_per_sample, int *sdm return ESP_OK; } + esp_err_t i2s_set_clk(i2s_port_t i2s_num, uint32_t rate, i2s_bits_per_sample_t bits, i2s_channel_t ch) { int factor = (256%bits)? 384 : 256; // According to hardware codec requirement(supported 256fs or 384fs) @@ -357,29 +333,13 @@ esp_err_t i2s_set_clk(i2s_port_t i2s_num, uint32_t rate, i2s_bits_per_sample_t b i2s_stop(i2s_num); - - uint32_t cur_mode = 0; + i2s_hal_set_tx_mode(&(p_i2s_obj[i2s_num]->hal), ch, bits); + i2s_hal_set_rx_mode(&(p_i2s_obj[i2s_num]->hal), ch, bits); if (p_i2s_obj[i2s_num]->channel_num != ch) { p_i2s_obj[i2s_num]->channel_num = (ch == 2) ? 2 : 1; - cur_mode = I2S[i2s_num]->fifo_conf.tx_fifo_mod; - I2S[i2s_num]->fifo_conf.tx_fifo_mod = (ch == 2) ? cur_mode - 1 : cur_mode + 1; - cur_mode = I2S[i2s_num]->fifo_conf.rx_fifo_mod; - I2S[i2s_num]->fifo_conf.rx_fifo_mod = (ch == 2) ? cur_mode -1 : cur_mode + 1; - I2S[i2s_num]->conf_chan.tx_chan_mod = (ch == 2) ? 0 : 1; - I2S[i2s_num]->conf_chan.rx_chan_mod = (ch == 2) ? 0 : 1; } if (bits != p_i2s_obj[i2s_num]->bits_per_sample) { - - //change fifo mode - if (p_i2s_obj[i2s_num]->bits_per_sample <= 16 && bits > 16) { - I2S[i2s_num]->fifo_conf.tx_fifo_mod += 2; - I2S[i2s_num]->fifo_conf.rx_fifo_mod += 2; - } else if (p_i2s_obj[i2s_num]->bits_per_sample > 16 && bits <= 16) { - I2S[i2s_num]->fifo_conf.tx_fifo_mod -= 2; - I2S[i2s_num]->fifo_conf.rx_fifo_mod -= 2; - } - p_i2s_obj[i2s_num]->bits_per_sample = bits; p_i2s_obj[i2s_num]->bytes_per_sample = p_i2s_obj[i2s_num]->bits_per_sample / 8; @@ -402,7 +362,7 @@ esp_err_t i2s_set_clk(i2s_port_t i2s_num, uint32_t rate, i2s_bits_per_sample_t b i2s_driver_uninstall(i2s_num); return ESP_ERR_NO_MEM; } - I2S[i2s_num]->out_link.addr = (uint32_t) p_i2s_obj[i2s_num]->tx->desc[0]; + i2s_hal_set_out_link_addr(&(p_i2s_obj[i2s_num]->hal), (uint32_t) p_i2s_obj[i2s_num]->tx->desc[0]); //destroy old tx dma if exist if (save_tx) { @@ -420,15 +380,7 @@ esp_err_t i2s_set_clk(i2s_port_t i2s_num, uint32_t rate, i2s_bits_per_sample_t b i2s_driver_uninstall(i2s_num); return ESP_ERR_NO_MEM; } -#ifdef CONFIG_IDF_TARGET_ESP32 - //On ESP32S2, the eof_num count in words. - I2S[i2s_num]->rx_eof_num = (p_i2s_obj[i2s_num]->dma_buf_len * p_i2s_obj[i2s_num]->channel_num * p_i2s_obj[i2s_num]->bytes_per_sample)/4; -#elif defined CONFIG_IDF_TARGET_ESP32S2BETA - //On ESP32S2, the eof_num count in bytes. - I2S[i2s_num]->rx_eof_num = (p_i2s_obj[i2s_num]->dma_buf_len * p_i2s_obj[i2s_num]->channel_num * p_i2s_obj[i2s_num]->bytes_per_sample); -#endif - I2S[i2s_num]->in_link.addr = (uint32_t) p_i2s_obj[i2s_num]->rx->desc[0]; - + i2s_hal_set_in_link(&(p_i2s_obj[i2s_num]->hal), p_i2s_obj[i2s_num]->dma_buf_len * p_i2s_obj[i2s_num]->channel_num * p_i2s_obj[i2s_num]->bytes_per_sample, (uint32_t) p_i2s_obj[i2s_num]->rx->desc[0]); //destroy old rx dma if exist if (save_rx) { i2s_destroy_dma_queue(i2s_num, save_rx); @@ -456,13 +408,16 @@ esp_err_t i2s_set_clk(i2s_port_t i2s_num, uint32_t rate, i2s_bits_per_sample_t b } else if (p_i2s_obj[i2s_num]->mode & I2S_MODE_PDM) { uint32_t b_clk = 0; if (p_i2s_obj[i2s_num]->mode & I2S_MODE_TX) { - int fp = I2S[i2s_num]->pdm_freq_conf.tx_pdm_fp; - int fs = I2S[i2s_num]->pdm_freq_conf.tx_pdm_fs; + int fp; + int fs; + i2s_hal_get_tx_pdm(&(p_i2s_obj[i2s_num]->hal), &fp, &fs); b_clk = rate * I2S_PDM_BCK_FACTOR * (fp / fs); fi2s_clk /= (I2S_PDM_BCK_FACTOR * (fp / fs)); } else if (p_i2s_obj[i2s_num]->mode & I2S_MODE_RX) { - b_clk = rate * I2S_PDM_BCK_FACTOR * (I2S[i2s_num]->pdm_conf.rx_sinc_dsr_16_en + 1); - fi2s_clk /= (I2S_PDM_BCK_FACTOR * (I2S[i2s_num]->pdm_conf.rx_sinc_dsr_16_en + 1)); + bool en; + i2s_hal_get_rx_sinc_dsr_16_en(&(p_i2s_obj[i2s_num]->hal), &en); + b_clk = rate * I2S_PDM_BCK_FACTOR * (en ? 2 : 1); + fi2s_clk /= (I2S_PDM_BCK_FACTOR * (en ? 2 : 1)); } int factor2 = 5 ; mclk = b_clk * factor2; @@ -485,39 +440,23 @@ esp_err_t i2s_set_clk(i2s_port_t i2s_num, uint32_t rate, i2s_bits_per_sample_t b if(p_i2s_obj[i2s_num]->use_apll && i2s_apll_calculate_fi2s(fi2s_clk, bits, &sdm0, &sdm1, &sdm2, &odir) == ESP_OK) { ESP_LOGD(I2S_TAG, "sdm0=%d, sdm1=%d, sdm2=%d, odir=%d", sdm0, sdm1, sdm2, odir); rtc_clk_apll_enable(1, sdm0, sdm1, sdm2, odir); - I2S[i2s_num]->clkm_conf.clkm_div_num = 1; - I2S[i2s_num]->clkm_conf.clkm_div_b = 0; - I2S[i2s_num]->clkm_conf.clkm_div_a = 1; - I2S[i2s_num]->sample_rate_conf.tx_bck_div_num = m_scale; - I2S[i2s_num]->sample_rate_conf.rx_bck_div_num = m_scale; -#ifdef CONFIG_IDF_TARGET_ESP32 - I2S[i2s_num]->clkm_conf.clka_en = 1; -#elif defined CONFIG_IDF_TARGET_ESP32S2BETA - I2S[i2s_num]->clkm_conf.clk_sel = 1; -#endif + i2s_hal_set_clk_div(&(p_i2s_obj[i2s_num]->hal), 1, 1, 0, m_scale, m_scale); + i2s_hal_set_clock_sel(&(p_i2s_obj[i2s_num]->hal), I2S_CLK_APLL); double fi2s_rate = i2s_apll_get_fi2s(bits, sdm0, sdm1, sdm2, odir); p_i2s_obj[i2s_num]->real_rate = fi2s_rate/bits/channel/m_scale; ESP_LOGI(I2S_TAG, "APLL: Req RATE: %d, real rate: %0.3f, BITS: %u, CLKM: %u, BCK_M: %u, MCLK: %0.3f, SCLK: %f, diva: %d, divb: %d", rate, fi2s_rate/bits/channel/m_scale, bits, 1, m_scale, fi2s_rate, fi2s_rate/8, 1, 0); } else { -#ifdef CONFIG_IDF_TARGET_ESP32 - I2S[i2s_num]->clkm_conf.clka_en = 0; -#elif defined CONFIG_IDF_TARGET_ESP32S2BETA - I2S[i2s_num]->clkm_conf.clk_sel = 2; -#endif - I2S[i2s_num]->clkm_conf.clkm_div_a = 63; - I2S[i2s_num]->clkm_conf.clkm_div_b = clkmDecimals; - I2S[i2s_num]->clkm_conf.clkm_div_num = clkmInteger; - I2S[i2s_num]->sample_rate_conf.tx_bck_div_num = bck; - I2S[i2s_num]->sample_rate_conf.rx_bck_div_num = bck; + i2s_hal_set_clock_sel(&(p_i2s_obj[i2s_num]->hal), I2S_CLK_D2CLK); + i2s_hal_set_clk_div(&(p_i2s_obj[i2s_num]->hal), clkmInteger, 63, clkmDecimals, bck, bck); double real_rate = (double) (I2S_BASE_CLK / (bck * bits * clkmInteger) / 2); p_i2s_obj[i2s_num]->real_rate = real_rate; ESP_LOGI(I2S_TAG, "PLL_D2: Req RATE: %d, real rate: %0.3f, BITS: %u, CLKM: %u, BCK: %u, MCLK: %0.3f, SCLK: %f, diva: %d, divb: %d", rate, real_rate, bits, clkmInteger, bck, (double)I2S_BASE_CLK / mclk, real_rate*bits*channel, 64, clkmDecimals); } - I2S[i2s_num]->sample_rate_conf.tx_bits_mod = bits; - I2S[i2s_num]->sample_rate_conf.rx_bits_mod = bits; + i2s_hal_set_tx_bits_mod(&(p_i2s_obj[i2s_num]->hal), bits); + i2s_hal_set_rx_bits_mod(&(p_i2s_obj[i2s_num]->hal), bits); // wait all writing on-going finish if ((p_i2s_obj[i2s_num]->mode & I2S_MODE_TX) && p_i2s_obj[i2s_num]->tx) { @@ -533,15 +472,13 @@ esp_err_t i2s_set_clk(i2s_port_t i2s_num, uint32_t rate, i2s_bits_per_sample_t b static void IRAM_ATTR i2s_intr_handler_default(void *arg) { i2s_obj_t *p_i2s = (i2s_obj_t*) arg; - uint8_t i2s_num = p_i2s->i2s_num; - i2s_dev_t* i2s_reg = I2S[i2s_num]; - - typeof(i2s_reg->int_st) int_st_val = i2s_reg->int_st; - if(int_st_val.val == 0) { + uint32_t status; + i2s_hal_get_intr_status(&(p_i2s->hal), &status); + if(status == 0) { //Avoid spurious interrupt return; } - + i2s_event_t i2s_event; int dummy; @@ -549,8 +486,8 @@ static void IRAM_ATTR i2s_intr_handler_default(void *arg) lldesc_t *finish_desc; - if (int_st_val.out_dscr_err || int_st_val.in_dscr_err) { - ESP_EARLY_LOGE(I2S_TAG, "dma error, interrupt status: 0x%08x", int_st_val.val); + if ((status & I2S_INTR_OUT_DSCR_ERR) || (status & I2S_INTR_IN_DSCR_ERR)) { + ESP_EARLY_LOGE(I2S_TAG, "dma error, interrupt status: 0x%08x", status); if (p_i2s->i2s_queue) { i2s_event.type = I2S_EVENT_DMA_ERROR; if (xQueueIsQueueFullFromISR(p_i2s->i2s_queue)) { @@ -560,8 +497,8 @@ static void IRAM_ATTR i2s_intr_handler_default(void *arg) } } - if (int_st_val.out_eof && p_i2s->tx) { - finish_desc = (lldesc_t*) i2s_reg->out_eof_des_addr; + if ((status & I2S_INTR_OUT_EOF) && p_i2s->tx) { + i2s_hal_get_out_eof_des_addr(&(p_i2s->hal), (uint32_t *)&finish_desc); // All buffers are empty. This means we have an underflow on our hands. if (xQueueIsQueueFullFromISR(p_i2s->tx->queue)) { xQueueReceiveFromISR(p_i2s->tx->queue, &dummy, &high_priority_task_awoken); @@ -582,9 +519,9 @@ static void IRAM_ATTR i2s_intr_handler_default(void *arg) } } - if (int_st_val.in_suc_eof && p_i2s->rx) { + if ((status & I2S_INTR_IN_SUC_EOF) && p_i2s->rx) { // All buffers are full. This means we have an overflow. - finish_desc = (lldesc_t*) i2s_reg->in_eof_des_addr; + i2s_hal_get_in_eof_des_addr(&(p_i2s->hal), (uint32_t *)&finish_desc); if (xQueueIsQueueFullFromISR(p_i2s->rx->queue)) { xQueueReceiveFromISR(p_i2s->rx->queue, &dummy, &high_priority_task_awoken); } @@ -597,7 +534,7 @@ static void IRAM_ATTR i2s_intr_handler_default(void *arg) xQueueSendFromISR(p_i2s->i2s_queue, (void * )&i2s_event, &high_priority_task_awoken); } } - i2s_reg->int_clr.val = int_st_val.val; + i2s_hal_clear_intr_status(&(p_i2s->hal), status); if (high_priority_task_awoken == pdTRUE) { portYIELD_FROM_ISR(); @@ -698,35 +635,24 @@ static i2s_dma_t *i2s_create_dma_queue(i2s_port_t i2s_num, int dma_buf_count, in return dma; } - esp_err_t i2s_start(i2s_port_t i2s_num) { I2S_CHECK((i2s_num < I2S_NUM_MAX), "i2s_num error", ESP_ERR_INVALID_ARG); //start DMA link I2S_ENTER_CRITICAL(); i2s_reset_fifo(i2s_num); - //reset dma - I2S[i2s_num]->lc_conf.in_rst = 1; - I2S[i2s_num]->lc_conf.in_rst = 0; - I2S[i2s_num]->lc_conf.out_rst = 1; - I2S[i2s_num]->lc_conf.out_rst = 0; - I2S[i2s_num]->conf.tx_reset = 1; - I2S[i2s_num]->conf.tx_reset = 0; - I2S[i2s_num]->conf.rx_reset = 1; - I2S[i2s_num]->conf.rx_reset = 0; + i2s_hal_reset(&(p_i2s_obj[i2s_num]->hal)); esp_intr_disable(p_i2s_obj[i2s_num]->i2s_isr_handle); - I2S[i2s_num]->int_clr.val = 0xFFFFFFFF; + i2s_hal_clear_intr_status(&(p_i2s_obj[i2s_num]->hal), I2S_INTR_MAX); if (p_i2s_obj[i2s_num]->mode & I2S_MODE_TX) { i2s_enable_tx_intr(i2s_num); - I2S[i2s_num]->out_link.start = 1; - I2S[i2s_num]->conf.tx_start = 1; + i2s_hal_start_tx(&(p_i2s_obj[i2s_num]->hal)); } if (p_i2s_obj[i2s_num]->mode & I2S_MODE_RX) { i2s_enable_rx_intr(i2s_num); - I2S[i2s_num]->in_link.start = 1; - I2S[i2s_num]->conf.rx_start = 1; + i2s_hal_start_rx(&(p_i2s_obj[i2s_num]->hal)); } esp_intr_enable(p_i2s_obj[i2s_num]->i2s_isr_handle); I2S_EXIT_CRITICAL(); @@ -739,16 +665,16 @@ esp_err_t i2s_stop(i2s_port_t i2s_num) I2S_ENTER_CRITICAL(); esp_intr_disable(p_i2s_obj[i2s_num]->i2s_isr_handle); if (p_i2s_obj[i2s_num]->mode & I2S_MODE_TX) { - I2S[i2s_num]->out_link.stop = 1; - I2S[i2s_num]->conf.tx_start = 0; + i2s_hal_stop_tx(&(p_i2s_obj[i2s_num]->hal)); i2s_disable_tx_intr(i2s_num); } if (p_i2s_obj[i2s_num]->mode & I2S_MODE_RX) { - I2S[i2s_num]->in_link.stop = 1; - I2S[i2s_num]->conf.rx_start = 0; + i2s_hal_stop_rx(&(p_i2s_obj[i2s_num]->hal)); i2s_disable_rx_intr(i2s_num); } - I2S[i2s_num]->int_clr.val = I2S[i2s_num]->int_st.val; //clear pending interrupt + uint32_t mask; + i2s_hal_get_intr_status(&(p_i2s_obj[i2s_num]->hal), &mask); + i2s_hal_clear_intr_status(&(p_i2s_obj[i2s_num]->hal), mask); I2S_EXIT_CRITICAL(); return ESP_OK; } @@ -875,7 +801,7 @@ esp_err_t i2s_set_sample_rates(i2s_port_t i2s_num, uint32_t rate) esp_err_t i2s_set_pdm_rx_down_sample(i2s_port_t i2s_num, i2s_pdm_dsr_t dsr) { I2S_CHECK((i2s_num < I2S_NUM_MAX), "i2s_num error", ESP_ERR_INVALID_ARG); - I2S[i2s_num]->pdm_conf.rx_sinc_dsr_16_en = dsr; + i2s_hal_set_pdm_rx_down_sample(&(p_i2s_obj[i2s_num]->hal), dsr); return i2s_set_clk(i2s_num, p_i2s_obj[i2s_num]->sample_rate, p_i2s_obj[i2s_num]->bits_per_sample, p_i2s_obj[i2s_num]->channel_num); } #endif @@ -900,137 +826,13 @@ static esp_err_t i2s_param_config(i2s_port_t i2s_num, const i2s_config_t *i2s_co } // configure I2S data port interface. i2s_reset_fifo(i2s_num); - //reset i2s - I2S[i2s_num]->conf.tx_reset = 1; - I2S[i2s_num]->conf.tx_reset = 0; - I2S[i2s_num]->conf.rx_reset = 1; - I2S[i2s_num]->conf.rx_reset = 0; - - //reset dma - I2S[i2s_num]->lc_conf.in_rst = 1; - I2S[i2s_num]->lc_conf.in_rst = 0; - I2S[i2s_num]->lc_conf.out_rst = 1; - I2S[i2s_num]->lc_conf.out_rst = 0; - - //Enable and configure DMA - I2S[i2s_num]->lc_conf.check_owner = 0; - I2S[i2s_num]->lc_conf.out_loop_test = 0; - I2S[i2s_num]->lc_conf.out_auto_wrback = 0; - I2S[i2s_num]->lc_conf.out_data_burst_en = 0; - I2S[i2s_num]->lc_conf.outdscr_burst_en = 0; - I2S[i2s_num]->lc_conf.out_no_restart_clr = 0; - I2S[i2s_num]->lc_conf.indscr_burst_en = 0; - I2S[i2s_num]->lc_conf.out_eof_mode = 1; - - I2S[i2s_num]->conf2.lcd_en = 0; - I2S[i2s_num]->conf2.camera_en = 0; - I2S[i2s_num]->pdm_conf.pcm2pdm_conv_en = 0; - I2S[i2s_num]->pdm_conf.pdm2pcm_conv_en = 0; - - I2S[i2s_num]->fifo_conf.dscr_en = 0; - - I2S[i2s_num]->conf_chan.tx_chan_mod = i2s_config->channel_format < I2S_CHANNEL_FMT_ONLY_RIGHT ? i2s_config->channel_format : (i2s_config->channel_format >> 1); // 0-two channel;1-right;2-left;3-righ;4-left - I2S[i2s_num]->fifo_conf.tx_fifo_mod = i2s_config->channel_format < I2S_CHANNEL_FMT_ONLY_RIGHT ? 0 : 1; // 0-right&left channel;1-one channel - I2S[i2s_num]->conf.tx_mono = 0; - - I2S[i2s_num]->conf_chan.rx_chan_mod = i2s_config->channel_format < I2S_CHANNEL_FMT_ONLY_RIGHT ? i2s_config->channel_format : (i2s_config->channel_format >> 1); // 0-two channel;1-right;2-left;3-righ;4-left - I2S[i2s_num]->fifo_conf.rx_fifo_mod = i2s_config->channel_format < I2S_CHANNEL_FMT_ONLY_RIGHT ? 0 : 1; // 0-right&left channel;1-one channel - I2S[i2s_num]->conf.rx_mono = 0; - - I2S[i2s_num]->fifo_conf.dscr_en = 1;//connect dma to fifo - - I2S[i2s_num]->conf.tx_start = 0; - I2S[i2s_num]->conf.rx_start = 0; - - if (i2s_config->mode & I2S_MODE_TX) { - I2S[i2s_num]->conf.tx_msb_right = 1; - I2S[i2s_num]->conf.tx_right_first = 0; - - I2S[i2s_num]->conf.tx_slave_mod = 0; // Master - I2S[i2s_num]->fifo_conf.tx_fifo_mod_force_en = 1; - - if (i2s_config->mode & I2S_MODE_SLAVE) { - I2S[i2s_num]->conf.tx_slave_mod = 1;//TX Slave - } - } - - if (i2s_config->mode & I2S_MODE_RX) { - I2S[i2s_num]->conf.rx_msb_right = 1; - I2S[i2s_num]->conf.rx_right_first = 0; - I2S[i2s_num]->conf.rx_slave_mod = 0; // Master - I2S[i2s_num]->fifo_conf.rx_fifo_mod_force_en = 1; - - if (i2s_config->mode & I2S_MODE_SLAVE) { - I2S[i2s_num]->conf.rx_slave_mod = 1;//RX Slave - } - } - - if (i2s_config->mode & (I2S_MODE_DAC_BUILT_IN | I2S_MODE_ADC_BUILT_IN)) { - I2S[i2s_num]->conf2.lcd_en = 1; - I2S[i2s_num]->conf.tx_right_first = 1; - I2S[i2s_num]->conf2.camera_en = 0; - } - -#if SOC_I2S_SUPPORT_PDM - if (i2s_config->mode & I2S_MODE_PDM) { - I2S[i2s_num]->fifo_conf.rx_fifo_mod_force_en = 1; - I2S[i2s_num]->fifo_conf.tx_fifo_mod_force_en = 1; - - I2S[i2s_num]->pdm_freq_conf.tx_pdm_fp = 960; - I2S[i2s_num]->pdm_freq_conf.tx_pdm_fs = i2s_config->sample_rate / 1000 * 10; - I2S[i2s_num]->pdm_conf.tx_sinc_osr2 = I2S[i2s_num]->pdm_freq_conf.tx_pdm_fp / I2S[i2s_num]->pdm_freq_conf.tx_pdm_fs; - - I2S[i2s_num]->pdm_conf.rx_sinc_dsr_16_en = 0; - I2S[i2s_num]->pdm_conf.rx_pdm_en = 1; - I2S[i2s_num]->pdm_conf.tx_pdm_en = 1; - - I2S[i2s_num]->pdm_conf.pcm2pdm_conv_en = 1; - I2S[i2s_num]->pdm_conf.pdm2pcm_conv_en = 1; - } else { - I2S[i2s_num]->pdm_conf.rx_pdm_en = 0; - I2S[i2s_num]->pdm_conf.tx_pdm_en = 0; - } -#else - I2S[i2s_num]->pdm_conf.rx_pdm_en = 0; - I2S[i2s_num]->pdm_conf.tx_pdm_en = 0; -#endif - if (i2s_config->communication_format & I2S_COMM_FORMAT_I2S) { - I2S[i2s_num]->conf.tx_short_sync = 0; - I2S[i2s_num]->conf.rx_short_sync = 0; - I2S[i2s_num]->conf.tx_msb_shift = 1; - I2S[i2s_num]->conf.rx_msb_shift = 1; - if (i2s_config->communication_format & I2S_COMM_FORMAT_I2S_LSB) { - if (i2s_config->mode & I2S_MODE_TX) { - I2S[i2s_num]->conf.tx_msb_shift = 0; - } - if (i2s_config->mode & I2S_MODE_RX) { - I2S[i2s_num]->conf.rx_msb_shift = 0; - } - } - } - - if (i2s_config->communication_format & I2S_COMM_FORMAT_PCM) { - I2S[i2s_num]->conf.tx_msb_shift = 0; - I2S[i2s_num]->conf.rx_msb_shift = 0; - I2S[i2s_num]->conf.tx_short_sync = 0; - I2S[i2s_num]->conf.rx_short_sync = 0; - if (i2s_config->communication_format & I2S_COMM_FORMAT_PCM_SHORT) { - if (i2s_config->mode & I2S_MODE_TX) { - I2S[i2s_num]->conf.tx_short_sync = 1; - } - if (i2s_config->mode & I2S_MODE_RX) { - I2S[i2s_num]->conf.rx_short_sync = 1; - } - } - } + i2s_hal_config_param(&(p_i2s_obj[i2s_num]->hal), i2s_config); if ((p_i2s_obj[i2s_num]->mode & I2S_MODE_RX) && (p_i2s_obj[i2s_num]->mode & I2S_MODE_TX)) { - I2S[i2s_num]->conf.sig_loopback = 1; + i2s_hal_enable_sig_loopback(&(p_i2s_obj[i2s_num]->hal)); if (p_i2s_obj[i2s_num]->mode & I2S_MODE_MASTER) { - I2S[i2s_num]->conf.tx_slave_mod = 0; //MASTER Slave - I2S[i2s_num]->conf.rx_slave_mod = 1; //RX Slave + i2s_hal_enable_master_mode(&(p_i2s_obj[i2s_num]->hal)); } else { - I2S[i2s_num]->conf.tx_slave_mod = 1; //RX Slave - I2S[i2s_num]->conf.rx_slave_mod = 1; //RX Slave + i2s_hal_enable_slave_mode(&(p_i2s_obj[i2s_num]->hal)); } } @@ -1077,6 +879,14 @@ esp_err_t i2s_driver_install(i2s_port_t i2s_num, const i2s_config_t *i2s_config, } memset(p_i2s_obj[i2s_num], 0, sizeof(i2s_obj_t)); + portMUX_TYPE i2s_spinlock_unlocked[1] = {portMUX_INITIALIZER_UNLOCKED}; + for (int x = 0; x < I2S_NUM_MAX; x++) { + i2s_spinlock[x] = i2s_spinlock_unlocked[0]; + } + //To make sure hardware is enabled before any hardware register operations. + periph_module_enable(i2s_periph_signal[i2s_num].module); + i2s_hal_init(&(p_i2s_obj[i2s_num]->hal), i2s_num); + p_i2s_obj[i2s_num]->i2s_num = i2s_num; p_i2s_obj[i2s_num]->dma_buf_count = i2s_config->dma_buf_count; p_i2s_obj[i2s_num]->dma_buf_len = i2s_config->dma_buf_len; @@ -1101,9 +911,6 @@ esp_err_t i2s_driver_install(i2s_port_t i2s_num, const i2s_config_t *i2s_config, } #endif //CONFIG_PM_ENABLE - //To make sure hardware is enabled before any hardware register operations. - periph_module_enable(i2s_periph_signal[i2s_num].module); - //initial interrupt err = i2s_isr_register(i2s_num, i2s_config->intr_alloc_flags, i2s_intr_handler_default, p_i2s_obj[i2s_num], &p_i2s_obj[i2s_num]->i2s_isr_handle); if (err != ESP_OK) { @@ -1342,4 +1149,4 @@ esp_err_t i2s_read(i2s_port_t i2s_num, void *dest, size_t size, size_t *bytes_re #endif xSemaphoreGive(p_i2s_obj[i2s_num]->rx->mux); return ESP_OK; -} +} \ No newline at end of file diff --git a/components/driver/include/driver/i2s.h b/components/driver/include/driver/i2s.h index aaf9c8810..40b786bc8 100644 --- a/components/driver/include/driver/i2s.h +++ b/components/driver/include/driver/i2s.h @@ -12,14 +12,15 @@ // See the License for the specific language governing permissions and // limitations under the License. -#ifndef _DRIVER_I2S_H_ -#define _DRIVER_I2S_H_ +#pragma once + #include "esp_err.h" #include #include "soc/soc.h" #include "soc/gpio_periph.h" #include "soc/i2s_periph.h" #include "soc/rtc_periph.h" +#include "soc/i2s_caps.h" #include "esp32/rom/gpio.h" #include "esp_attr.h" #include "esp_intr_alloc.h" @@ -27,183 +28,15 @@ #include "driver/adc.h" #include "freertos/FreeRTOS.h" #include "freertos/semphr.h" +#include "hal/i2s_hal.h" +#include "hal/i2s_types.h" #ifdef __cplusplus extern "C" { #endif -/** - * @brief I2S bit width per sample. - * - */ -typedef enum { - I2S_BITS_PER_SAMPLE_8BIT = 8, /*!< I2S bits per sample: 8-bits*/ - I2S_BITS_PER_SAMPLE_16BIT = 16, /*!< I2S bits per sample: 16-bits*/ - I2S_BITS_PER_SAMPLE_24BIT = 24, /*!< I2S bits per sample: 24-bits*/ - I2S_BITS_PER_SAMPLE_32BIT = 32, /*!< I2S bits per sample: 32-bits*/ -} i2s_bits_per_sample_t; - -/** - * @brief I2S channel. - * - */ -typedef enum { - I2S_CHANNEL_MONO = 1, /*!< I2S 1 channel (mono)*/ - I2S_CHANNEL_STEREO = 2 /*!< I2S 2 channel (stereo)*/ -} i2s_channel_t; - -/** - * @brief I2S communication standard format - * - */ -typedef enum { - I2S_COMM_FORMAT_I2S = 0x01, /*!< I2S communication format I2S*/ - I2S_COMM_FORMAT_I2S_MSB = 0x02, /*!< I2S format MSB*/ - I2S_COMM_FORMAT_I2S_LSB = 0x04, /*!< I2S format LSB*/ - I2S_COMM_FORMAT_PCM = 0x08, /*!< I2S communication format PCM*/ - I2S_COMM_FORMAT_PCM_SHORT = 0x10, /*!< PCM Short*/ - I2S_COMM_FORMAT_PCM_LONG = 0x20, /*!< PCM Long*/ -} i2s_comm_format_t; - - -/** - * @brief I2S channel format type - */ -typedef enum { - I2S_CHANNEL_FMT_RIGHT_LEFT = 0x00, - I2S_CHANNEL_FMT_ALL_RIGHT, - I2S_CHANNEL_FMT_ALL_LEFT, - I2S_CHANNEL_FMT_ONLY_RIGHT, - I2S_CHANNEL_FMT_ONLY_LEFT, -} i2s_channel_fmt_t; - -/** - * @brief PDM sample rate ratio, measured in Hz. - * - */ -typedef enum { - PDM_SAMPLE_RATE_RATIO_64, - PDM_SAMPLE_RATE_RATIO_128, -} pdm_sample_rate_ratio_t; - -/** - * @brief PDM PCM convter enable/disable. - * - */ -typedef enum { - PDM_PCM_CONV_ENABLE, - PDM_PCM_CONV_DISABLE, -} pdm_pcm_conv_t; - - -/** - * @brief I2S Peripheral, 0 & 1. - * - */ -typedef enum { - I2S_NUM_0 = 0x0, /*!< I2S 0*/ -#if SOC_I2S_PERIPH_NUM > 1 - I2S_NUM_1, /*!< I2S 1*/ -#endif - I2S_NUM_MAX, -} i2s_port_t; - -/** - * @brief I2S Mode, defaut is I2S_MODE_MASTER | I2S_MODE_TX - * - * @note PDM and built-in DAC functions are only supported on I2S0 for current ESP32 chip. - * - */ -typedef enum { - I2S_MODE_MASTER = 1, - I2S_MODE_SLAVE = 2, - I2S_MODE_TX = 4, - I2S_MODE_RX = 8, - I2S_MODE_DAC_BUILT_IN = 16, /*!< Output I2S data to built-in DAC, no matter the data format is 16bit or 32 bit, the DAC module will only take the 8bits from MSB*/ - I2S_MODE_ADC_BUILT_IN = 32, /*!< Input I2S data from built-in ADC, each data can be 12-bit width at most*/ -#if SOC_I2S_SUPPORT_PDM - I2S_MODE_PDM = 64, -#endif -} i2s_mode_t; - - - -/** - * @brief I2S configuration parameters for i2s_param_config function - * - */ -typedef struct { - i2s_mode_t mode; /*!< I2S work mode*/ - int sample_rate; /*!< I2S sample rate*/ - i2s_bits_per_sample_t bits_per_sample; /*!< I2S bits per sample*/ - i2s_channel_fmt_t channel_format; /*!< I2S channel format */ - i2s_comm_format_t communication_format; /*!< I2S communication format */ - int intr_alloc_flags; /*!< Flags used to allocate the interrupt. One or multiple (ORred) ESP_INTR_FLAG_* values. See esp_intr_alloc.h for more info */ - int dma_buf_count; /*!< I2S DMA Buffer Count */ - int dma_buf_len; /*!< I2S DMA Buffer Length */ - bool use_apll; /*!< I2S using APLL as main I2S clock, enable it to get accurate clock */ - bool tx_desc_auto_clear; /*!< I2S auto clear tx descriptor if there is underflow condition (helps in avoiding noise in case of data unavailability) */ - int fixed_mclk; /*!< I2S using fixed MCLK output. If use_apll = true and fixed_mclk > 0, then the clock output for i2s is fixed and equal to the fixed_mclk value.*/ -} i2s_config_t; - -/** - * @brief I2S event types - * - */ -typedef enum { - I2S_EVENT_DMA_ERROR, - I2S_EVENT_TX_DONE, /*!< I2S DMA finish sent 1 buffer*/ - I2S_EVENT_RX_DONE, /*!< I2S DMA finish received 1 buffer*/ - I2S_EVENT_MAX, /*!< I2S event max index*/ -} i2s_event_type_t; - -/** - * @brief I2S DAC mode for i2s_set_dac_mode. - * - * @note PDM and built-in DAC functions are only supported on I2S0 for current ESP32 chip. - */ -typedef enum { - I2S_DAC_CHANNEL_DISABLE = 0, /*!< Disable I2S built-in DAC signals*/ - I2S_DAC_CHANNEL_RIGHT_EN = 1, /*!< Enable I2S built-in DAC right channel, maps to DAC channel 1 on GPIO25*/ - I2S_DAC_CHANNEL_LEFT_EN = 2, /*!< Enable I2S built-in DAC left channel, maps to DAC channel 2 on GPIO26*/ - I2S_DAC_CHANNEL_BOTH_EN = 0x3, /*!< Enable both of the I2S built-in DAC channels.*/ - I2S_DAC_CHANNEL_MAX = 0x4, /*!< I2S built-in DAC mode max index*/ -} i2s_dac_mode_t; - -/** - * @brief Event structure used in I2S event queue - * - */ -typedef struct { - i2s_event_type_t type; /*!< I2S event type */ - size_t size; /*!< I2S data size for I2S_DATA event*/ -} i2s_event_t; - -#define I2S_PIN_NO_CHANGE (-1) /*!< Use in i2s_pin_config_t for pins which should not be changed */ - -/** - * @brief I2S pin number for i2s_set_pin - * - */ -typedef struct { - int bck_io_num; /*!< BCK in out pin*/ - int ws_io_num; /*!< WS in out pin*/ - int data_out_num; /*!< DATA out pin*/ - int data_in_num; /*!< DATA in pin*/ -} i2s_pin_config_t; - -#if SOC_I2S_SUPPORT_PDM -/** - * @brief I2S PDM RX downsample mode - */ -typedef enum { - I2S_PDM_DSR_8S = 0, /*!< downsampling number is 8 for PDM RX mode*/ - I2S_PDM_DSR_16S, /*!< downsampling number is 16 for PDM RX mode*/ - I2S_PDM_DSR_MAX, -} i2s_pdm_dsr_t; -#endif - typedef intr_handle_t i2s_isr_handle_t; + /** * @brief Set I2S pin number * @@ -498,5 +331,3 @@ esp_err_t i2s_adc_disable(i2s_port_t i2s_num); #ifdef __cplusplus } #endif - -#endif /* _DRIVER_I2S_H_ */ diff --git a/components/soc/CMakeLists.txt b/components/soc/CMakeLists.txt index 933954d65..af8713163 100644 --- a/components/soc/CMakeLists.txt +++ b/components/soc/CMakeLists.txt @@ -18,6 +18,7 @@ list(APPEND srcs "src/hal/spi_slave_hal_iram.c" "src/soc_include_legacy_warn.c" "src/hal/pcnt_hal.c" + "src/hal/i2s_hal.c" ) # TODO: SPI Flash HAL for ESP32S2Beta also diff --git a/components/soc/esp32/i2s_periph.c b/components/soc/esp32/i2s_periph.c index cd9fef98e..84985aaf6 100644 --- a/components/soc/esp32/i2s_periph.c +++ b/components/soc/esp32/i2s_periph.c @@ -18,7 +18,7 @@ /* Bunch of constants for every I2S peripheral: GPIO signals, irqs, hw addr of registers etc */ -const i2s_signal_conn_t i2s_periph_signal[SOC_I2S_PERIPH_NUM] = { +const i2s_signal_conn_t i2s_periph_signal[SOC_I2S_NUM] = { { .o_bck_in_sig = I2S0O_BCK_IN_IDX, .o_ws_in_sig = I2S0O_WS_IN_IDX, diff --git a/components/soc/esp32/include/hal/i2s_ll.h b/components/soc/esp32/include/hal/i2s_ll.h new file mode 100644 index 000000000..75c58d9ce --- /dev/null +++ b/components/soc/esp32/include/hal/i2s_ll.h @@ -0,0 +1,837 @@ +// Copyright 2015-2019 Espressif Systems (Shanghai) PTE LTD +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +/******************************************************************************* + * NOTICE + * The hal is not public api, don't use in application code. + * See readme.md in soc/include/hal/readme.md + ******************************************************************************/ + +// The LL layer for ESP32 I2S register operations + +#pragma once + +#include +#include "soc/rtc_periph.h" +#include "soc/rtc.h" +#include "soc/efuse_periph.h" +#include "soc/i2s_periph.h" +#include "hal/i2s_types.h" + +#ifdef __cplusplus +extern "C" { +#endif + +// Get I2S hardware instance with giving i2s num +#define I2S_LL_GET_HW(num) (((num) == 0) ? (&I2S0) : (((num) == 1) ? (&I2S1) : NULL)) + +#define I2S_INTR_IN_SUC_EOF BIT(9) +#define I2S_INTR_OUT_EOF BIT(12) +#define I2S_INTR_IN_DSCR_ERR BIT(13) +#define I2S_INTR_OUT_DSCR_ERR BIT(14) +#define I2S_INTR_MAX (0xFFFFFFFF) + +/** + * @brief Reset rx fifo + * + * @param hw Peripheral I2S hardware instance address. + */ +static inline void i2s_ll_reset_rx_fifo(i2s_dev_t *hw) +{ + hw->conf.rx_fifo_reset = 1; + hw->conf.rx_fifo_reset = 0; +} + +/** + * @brief Reset tx fifo + * + * @param hw Peripheral I2S hardware instance address. + */ +static inline void i2s_ll_reset_tx_fifo(i2s_dev_t *hw) +{ + hw->conf.tx_fifo_reset = 1; + hw->conf.tx_fifo_reset = 0; +} + +/** + * @brief Enable rx interrupt + * + * @param hw Peripheral I2S hardware instance address. + */ +static inline void i2s_ll_enable_rx_intr(i2s_dev_t *hw) +{ + hw->int_ena.in_suc_eof = 1; + hw->int_ena.in_dscr_err = 1; +} + +/** + * @brief Disable rx interrupt + * + * @param hw Peripheral I2S hardware instance address. + */ +static inline void i2s_ll_disable_rx_intr(i2s_dev_t *hw) +{ + hw->int_ena.in_suc_eof = 0; + hw->int_ena.in_dscr_err = 0; +} + +/** + * @brief Disable tx interrupt + * + * @param hw Peripheral I2S hardware instance address. + */ +static inline void i2s_ll_disable_tx_intr(i2s_dev_t *hw) +{ + hw->int_ena.out_eof = 0; + hw->int_ena.out_dscr_err = 0; +} + +/** + * @brief Enable tx interrupt + * + * @param hw Peripheral I2S hardware instance address. + */ +static inline void i2s_ll_enable_tx_intr(i2s_dev_t *hw) +{ + hw->int_ena.out_eof = 1; + hw->int_ena.out_dscr_err = 1; +} + +/** + * @brief Reset dma in + * + * @param hw Peripheral I2S hardware instance address. + */ +static inline void i2s_ll_reset_dma_in(i2s_dev_t *hw) +{ + hw->lc_conf.in_rst = 1; + hw->lc_conf.in_rst = 0; +} + +/** + * @brief Reset dma out + * + * @param hw Peripheral I2S hardware instance address. + */ +static inline void i2s_ll_reset_dma_out(i2s_dev_t *hw) +{ + hw->lc_conf.out_rst = 1; + hw->lc_conf.out_rst = 0; +} + +/** + * @brief Reset tx + * + * @param hw Peripheral I2S hardware instance address. + */ +static inline void i2s_ll_reset_tx(i2s_dev_t *hw) +{ + hw->conf.tx_reset = 1; + hw->conf.tx_reset = 0; +} + +/** + * @brief Reset rx + * + * @param hw Peripheral I2S hardware instance address. + */ +static inline void i2s_ll_reset_rx(i2s_dev_t *hw) +{ + hw->conf.rx_reset = 1; + hw->conf.rx_reset = 0; +} + +/** + * @brief Start out link + * + * @param hw Peripheral I2S hardware instance address. + */ +static inline void i2s_ll_start_out_link(i2s_dev_t *hw) +{ + hw->out_link.start = 1; +} + +/** + * @brief Start tx + * + * @param hw Peripheral I2S hardware instance address. + */ +static inline void i2s_ll_start_tx(i2s_dev_t *hw) +{ + hw->conf.tx_start = 1; +} + +/** + * @brief Start in link + * + * @param hw Peripheral I2S hardware instance address. + */ +static inline void i2s_ll_start_in_link(i2s_dev_t *hw) +{ + hw->in_link.start = 1; +} + +/** + * @brief Start rx + * + * @param hw Peripheral I2S hardware instance address. + */ +static inline void i2s_ll_start_rx(i2s_dev_t *hw) +{ + hw->conf.rx_start = 1; +} + +/** + * @brief Stop out link + * + * @param hw Peripheral I2S hardware instance address. + */ +static inline void i2s_ll_stop_out_link(i2s_dev_t *hw) +{ + hw->out_link.stop = 1; +} + +/** + * @brief Stop tx + * + * @param hw Peripheral I2S hardware instance address. + */ +static inline void i2s_ll_stop_tx(i2s_dev_t *hw) +{ + hw->conf.tx_start = 0; +} + +/** + * @brief Stop in link + * + * @param hw Peripheral I2S hardware instance address. + */ +static inline void i2s_ll_stop_in_link(i2s_dev_t *hw) +{ + hw->in_link.stop = 1; +} + +/** + * @brief Stop rx + * + * @param hw Peripheral I2S hardware instance address. + */ +static inline void i2s_ll_stop_rx(i2s_dev_t *hw) +{ + hw->conf.rx_start = 0; +} + +/** + * @brief Enable dma + * + * @param hw Peripheral I2S hardware instance address. + */ +static inline void i2s_ll_enable_dma(i2s_dev_t *hw) +{ + //Enable and configure DMA + typeof(hw->lc_conf) lc_conf; + lc_conf.val = 0; + lc_conf.out_eof_mode = 1; + hw->lc_conf.val = lc_conf.val; +} + +/** + * @brief Get I2S revision + * + * @param hw Peripheral I2S hardware instance address. + * @param val value to get revision + */ +static inline void i2s_ll_get_rev(i2s_dev_t *hw, uint32_t *val) +{ + if (GET_PERI_REG_BITS2(EFUSE_BLK0_RDATA3_REG, 1, 15) == 0) { + *val = 1; + } +} + +/** + * @brief Get I2S interrupt status + * + * @param hw Peripheral I2S hardware instance address. + * @param val value to get interrupt status + */ +static inline void i2s_ll_get_intr_status(i2s_dev_t *hw, uint32_t *val) +{ + *val = hw->int_st.val; +} + +/** + * @brief Clear I2S interrupt status + * + * @param hw Peripheral I2S hardware instance address. + * @param val value to clear interrupt status + */ +static inline void i2s_ll_clear_intr_status(i2s_dev_t *hw, uint32_t val) +{ + hw->int_clr.val = val; +} + +/** + * @brief Get I2S out eof des address + * + * @param hw Peripheral I2S hardware instance address. + * @param val value to get out eof des address + */ +static inline void i2s_ll_get_out_eof_des_addr(i2s_dev_t *hw, uint32_t *val) +{ + *val = hw->out_eof_des_addr; +} + +/** + * @brief Get I2S in eof des address + * + * @param hw Peripheral I2S hardware instance address. + * @param val value to get in eof des address + */ +static inline void i2s_ll_get_in_eof_des_addr(i2s_dev_t *hw, uint32_t *val) +{ + *val = hw->in_eof_des_addr; +} + +/** + * @brief Get I2S tx fifo mode + * + * @param hw Peripheral I2S hardware instance address. + * @param val value to get tx fifo mode + */ +static inline void i2s_ll_get_tx_fifo_mod(i2s_dev_t *hw, uint32_t *val) +{ + *val = hw->fifo_conf.tx_fifo_mod; +} + +/** + * @brief Set I2S tx fifo mode + * + * @param hw Peripheral I2S hardware instance address. + * @param val value to set tx fifo mode + */ +static inline void i2s_ll_set_tx_fifo_mod(i2s_dev_t *hw, uint32_t val) +{ + hw->fifo_conf.tx_fifo_mod = val; +} + +/** + * @brief Get I2S rx fifo mode + * + * @param hw Peripheral I2S hardware instance address. + * @param val value to get rx fifo mode + */ +static inline void i2s_ll_get_rx_fifo_mod(i2s_dev_t *hw, uint32_t *val) +{ + *val = hw->fifo_conf.rx_fifo_mod; +} + +/** + * @brief Set I2S rx fifo mode + * + * @param hw Peripheral I2S hardware instance address. + * @param val value to set rx fifo mode + */ +static inline void i2s_ll_set_rx_fifo_mod(i2s_dev_t *hw, uint32_t val) +{ + hw->fifo_conf.rx_fifo_mod = val; +} + +/** + * @brief Set I2S tx chan mode + * + * @param hw Peripheral I2S hardware instance address. + * @param val value to set tx chan mode + */ +static inline void i2s_ll_set_tx_chan_mod(i2s_dev_t *hw, uint32_t val) +{ + hw->conf_chan.tx_chan_mod = val; +} + +/** + * @brief Set I2S rx chan mode + * + * @param hw Peripheral I2S hardware instance address. + * @param val value to set rx chan mode + */ +static inline void i2s_ll_set_rx_chan_mod(i2s_dev_t *hw, uint32_t val) +{ + hw->conf_chan.rx_chan_mod = val; +} + +/** + * @brief Set I2S out link address + * + * @param hw Peripheral I2S hardware instance address. + * @param val value to set out link address + */ +static inline void i2s_ll_set_out_link_addr(i2s_dev_t *hw, uint32_t val) +{ + hw->out_link.addr = val; +} + +/** + * @brief Set I2S in link address + * + * @param hw Peripheral I2S hardware instance address. + * @param val value to set in link address + */ +static inline void i2s_ll_set_in_link_addr(i2s_dev_t *hw, uint32_t val) +{ + hw->in_link.addr = val; +} + +/** + * @brief Set I2S rx eof num + * + * @param hw Peripheral I2S hardware instance address. + * @param val value to set rx eof num + */ +static inline void i2s_ll_set_rx_eof_num(i2s_dev_t *hw, uint32_t val) +{ + // On ESP32, the eof_num count in words. + hw->rx_eof_num = val / 4; +} + +/** + * @brief Get I2S tx pdm fp + * + * @param hw Peripheral I2S hardware instance address. + * @param val value to get tx pdm fp + */ +static inline void i2s_ll_get_tx_pdm_fp(i2s_dev_t *hw, uint32_t *val) +{ + *val = hw->pdm_freq_conf.tx_pdm_fp; +} + +/** + * @brief Get I2S tx pdm fs + * + * @param hw Peripheral I2S hardware instance address. + * @param val value to get tx pdm fs + */ +static inline void i2s_ll_get_tx_pdm_fs(i2s_dev_t *hw, uint32_t *val) +{ + *val = hw->pdm_freq_conf.tx_pdm_fs; +} + +/** + * @brief Set I2S tx pdm fp + * + * @param hw Peripheral I2S hardware instance address. + * @param val value to set tx pdm fp + */ +static inline void i2s_ll_set_tx_pdm_fp(i2s_dev_t *hw, uint32_t val) +{ + hw->pdm_freq_conf.tx_pdm_fp = val; +} + +/** + * @brief Set I2S tx pdm fs + * + * @param hw Peripheral I2S hardware instance address. + * @param val value to set tx pdm fs + */ +static inline void i2s_ll_set_tx_pdm_fs(i2s_dev_t *hw, uint32_t val) +{ + hw->pdm_freq_conf.tx_pdm_fs = val; +} + +/** + * @brief Get I2S rx sinc dsr 16 en + * + * @param hw Peripheral I2S hardware instance address. + * @param val value to get rx sinc dsr 16 en + */ +static inline void i2s_ll_get_rx_sinc_dsr_16_en(i2s_dev_t *hw, bool *val) +{ + *val = hw->pdm_conf.rx_sinc_dsr_16_en; +} + +/** + * @brief Set I2S clkm div num + * + * @param hw Peripheral I2S hardware instance address. + * @param val value to set clkm div num + */ +static inline void i2s_ll_set_clkm_div_num(i2s_dev_t *hw, uint32_t val) +{ + hw->clkm_conf.clkm_div_num = val; +} + +/** + * @brief Set I2S clkm div b + * + * @param hw Peripheral I2S hardware instance address. + * @param val value to set clkm div b + */ +static inline void i2s_ll_set_clkm_div_b(i2s_dev_t *hw, uint32_t val) +{ + hw->clkm_conf.clkm_div_b = val; +} + +/** + * @brief Set I2S clkm div a + * + * @param hw Peripheral I2S hardware instance address. + * @param val value to set clkm div a + */ +static inline void i2s_ll_set_clkm_div_a(i2s_dev_t *hw, uint32_t val) +{ + hw->clkm_conf.clkm_div_a = val; +} + +/** + * @brief Set I2S tx bck div num + * + * @param hw Peripheral I2S hardware instance address. + * @param val value to set tx bck div num + */ +static inline void i2s_ll_set_tx_bck_div_num(i2s_dev_t *hw, uint32_t val) +{ + hw->sample_rate_conf.tx_bck_div_num = val; +} + +/** + * @brief Set I2S rx bck div num + * + * @param hw Peripheral I2S hardware instance address. + * @param val value to set rx bck div num + */ +static inline void i2s_ll_set_rx_bck_div_num(i2s_dev_t *hw, uint32_t val) +{ + hw->sample_rate_conf.rx_bck_div_num = val; +} + +/** + * @brief Set I2S clk sel + * + * @param hw Peripheral I2S hardware instance address. + * @param val value to set clk sel + */ +static inline void i2s_ll_set_clk_sel(i2s_dev_t *hw, uint32_t val) +{ + hw->clkm_conf.clka_en = (val == 1) ? 1 : 0; +} + +/** + * @brief Set I2S tx bits mod + * + * @param hw Peripheral I2S hardware instance address. + * @param val value to set tx bits mod + */ +static inline void i2s_ll_set_tx_bits_mod(i2s_dev_t *hw, uint32_t val) +{ + hw->sample_rate_conf.tx_bits_mod = val; +} + +/** + * @brief Set I2S rx bits mod + * + * @param hw Peripheral I2S hardware instance address. + * @param val value to set rx bits mod + */ +static inline void i2s_ll_set_rx_bits_mod(i2s_dev_t *hw, uint32_t val) +{ + hw->sample_rate_conf.rx_bits_mod = val; +} + +/** + * @brief Set I2S rx sinc dsr 16 en + * + * @param hw Peripheral I2S hardware instance address. + * @param val value to set rx sinc dsr 16 en + */ +static inline void i2s_ll_set_rx_sinc_dsr_16_en(i2s_dev_t *hw, bool val) +{ + hw->pdm_conf.rx_sinc_dsr_16_en = val; +} + +/** + * @brief Set I2S dscr en + * + * @param hw Peripheral I2S hardware instance address. + * @param val value to set dscr en + */ +static inline void i2s_ll_set_dscr_en(i2s_dev_t *hw, bool val) +{ + hw->fifo_conf.dscr_en = val; +} + +/** + * @brief Set I2S lcd en + * + * @param hw Peripheral I2S hardware instance address. + * @param val value to set lcd en + */ +static inline void i2s_ll_set_lcd_en(i2s_dev_t *hw, bool val) +{ + hw->conf2.lcd_en = val; +} + +/** + * @brief Set I2S camera en + * + * @param hw Peripheral I2S hardware instance address. + * @param val value to set camera en + */ +static inline void i2s_ll_set_camera_en(i2s_dev_t *hw, bool val) +{ + hw->conf2.camera_en = val; +} + +/** + * @brief Set I2S pcm2pdm conv en + * + * @param hw Peripheral I2S hardware instance address. + * @param val value to set pcm2pdm conv en + */ +static inline void i2s_ll_set_pcm2pdm_conv_en(i2s_dev_t *hw, bool val) +{ + hw->pdm_conf.pcm2pdm_conv_en = val; +} + +/** + * @brief Set I2S pdm2pcm conv en + * + * @param hw Peripheral I2S hardware instance address. + * @param val value to set pdm2pcm conv en + */ +static inline void i2s_ll_set_pdm2pcm_conv_en(i2s_dev_t *hw, bool val) +{ + hw->pdm_conf.pdm2pcm_conv_en = val; +} + +/** + * @brief Set I2S rx pdm en + * + * @param hw Peripheral I2S hardware instance address. + * @param val value to set rx pdm en + */ +static inline void i2s_ll_set_rx_pdm_en(i2s_dev_t *hw, bool val) +{ + hw->pdm_conf.rx_pdm_en = val; +} + +/** + * @brief Set I2S tx pdm en + * + * @param hw Peripheral I2S hardware instance address. + * @param val value to set tx pdm en + */ +static inline void i2s_ll_set_tx_pdm_en(i2s_dev_t *hw, bool val) +{ + hw->pdm_conf.tx_pdm_en = val; +} + +/** + * @brief Set I2S tx msb shift + * + * @param hw Peripheral I2S hardware instance address. + * @param val value to set tx msb shift + */ +static inline void i2s_ll_set_tx_msb_shift(i2s_dev_t *hw, uint32_t val) +{ + hw->conf.tx_msb_shift = val; +} + +/** + * @brief Set I2S rx msb shift + * + * @param hw Peripheral I2S hardware instance address. + * @param val value to set rx msb shift + */ +static inline void i2s_ll_set_rx_msb_shift(i2s_dev_t *hw, uint32_t val) +{ + hw->conf.rx_msb_shift = val; +} + +/** + * @brief Set I2S tx short sync + * + * @param hw Peripheral I2S hardware instance address. + * @param val value to set tx short sync + */ +static inline void i2s_ll_set_tx_short_sync(i2s_dev_t *hw, uint32_t val) +{ + hw->conf.tx_short_sync = val; +} + +/** + * @brief Set I2S rx short sync + * + * @param hw Peripheral I2S hardware instance address. + * @param val value to set rx short sync + */ +static inline void i2s_ll_set_rx_short_sync(i2s_dev_t *hw, uint32_t val) +{ + hw->conf.rx_short_sync = val; +} + +/** + * @brief Set I2S tx fifo mod force en + * + * @param hw Peripheral I2S hardware instance address. + * @param val value to set tx fifo mod force en + */ +static inline void i2s_ll_set_tx_fifo_mod_force_en(i2s_dev_t *hw, bool val) +{ + hw->fifo_conf.tx_fifo_mod_force_en = val; +} + +/** + * @brief Set I2S rx fifo mod force en + * + * @param hw Peripheral I2S hardware instance address. + * @param val value to set rx fifo mod force en + */ +static inline void i2s_ll_set_rx_fifo_mod_force_en(i2s_dev_t *hw, bool val) +{ + hw->fifo_conf.rx_fifo_mod_force_en = val; +} + +/** + * @brief Set I2S tx right first + * + * @param hw Peripheral I2S hardware instance address. + * @param val value to set tx right first + */ +static inline void i2s_ll_set_tx_right_first(i2s_dev_t *hw, uint32_t val) +{ + hw->conf.tx_right_first = val; +} + +/** + * @brief Set I2S rx right first + * + * @param hw Peripheral I2S hardware instance address. + * @param val value to set rx right first + */ +static inline void i2s_ll_set_rx_right_first(i2s_dev_t *hw, uint32_t val) +{ + hw->conf.rx_right_first = val; +} + +/** + * @brief Set I2S tx slave mod + * + * @param hw Peripheral I2S hardware instance address. + * @param val value to set tx slave mod + */ +static inline void i2s_ll_set_tx_slave_mod(i2s_dev_t *hw, uint32_t val) +{ + hw->conf.tx_slave_mod = val; +} + +/** + * @brief Set I2S rx slave mod + * + * @param hw Peripheral I2S hardware instance address. + * @param val value to set rx slave mod + */ +static inline void i2s_ll_set_rx_slave_mod(i2s_dev_t *hw, uint32_t val) +{ + hw->conf.rx_slave_mod = val; +} + +/** + * @brief Get I2S tx msb right + * + * @param hw Peripheral I2S hardware instance address. + * @param val value to get tx msb right + */ +static inline void i2s_ll_get_tx_msb_right(i2s_dev_t *hw, uint32_t *val) +{ + *val = hw->conf.tx_msb_right; +} + +/** + * @brief Get I2S rx msb right + * + * @param hw Peripheral I2S hardware instance address. + * @param val value to get rx msb right + */ +static inline void i2s_ll_get_rx_msb_right(i2s_dev_t *hw, uint32_t *val) +{ + *val = hw->conf.rx_msb_right; +} + +/** + * @brief Set I2S tx msb right + * + * @param hw Peripheral I2S hardware instance address. + * @param val value to set tx msb right + */ +static inline void i2s_ll_set_tx_msb_right(i2s_dev_t *hw, uint32_t val) +{ + hw->conf.tx_msb_right = val; +} + +/** + * @brief Set I2S rx msb right + * + * @param hw Peripheral I2S hardware instance address. + * @param val value to set rx msb right + */ +static inline void i2s_ll_set_rx_msb_right(i2s_dev_t *hw, uint32_t val) +{ + hw->conf.rx_msb_right = val; +} + +/** + * @brief Set I2S tx mono + * + * @param hw Peripheral I2S hardware instance address. + * @param val value to set tx mono + */ +static inline void i2s_ll_set_tx_mono(i2s_dev_t *hw, uint32_t val) +{ + hw->conf.tx_mono = val; +} + +/** + * @brief Set I2S rx mono + * + * @param hw Peripheral I2S hardware instance address. + * @param val value to set rx mono + */ +static inline void i2s_ll_set_rx_mono(i2s_dev_t *hw, uint32_t val) +{ + hw->conf.rx_mono = val; +} + +/** + * @brief Set I2S tx sinc osr2 + * + * @param hw Peripheral I2S hardware instance address. + * @param val value to set tx sinc osr2 + */ +static inline void i2s_ll_set_tx_sinc_osr2(i2s_dev_t *hw, uint32_t val) +{ + hw->pdm_conf.tx_sinc_osr2 = val; +} + +/** + * @brief Set I2S sig loopback + * + * @param hw Peripheral I2S hardware instance address. + * @param val value to set sig loopback + */ +static inline void i2s_ll_set_sig_loopback(i2s_dev_t *hw, uint32_t val) +{ + hw->conf.sig_loopback = val; +} + +#ifdef __cplusplus +} +#endif \ No newline at end of file diff --git a/components/soc/esp32/include/soc/i2s_caps.h b/components/soc/esp32/include/soc/i2s_caps.h index bddde5c61..9382268be 100644 --- a/components/soc/esp32/include/soc/i2s_caps.h +++ b/components/soc/esp32/include/soc/i2s_caps.h @@ -3,7 +3,6 @@ // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at -// // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software @@ -14,5 +13,26 @@ #pragma once -#define SOC_I2S_PERIPH_NUM (2) //ESP32 have 2 I2S +#ifdef __cplusplus +extern "C" { +#endif + +#define APLL_MIN_FREQ (250000000) +#define APLL_MAX_FREQ (500000000) +#define APLL_I2S_MIN_RATE (10675) //in Hz, I2S Clock rate limited by hardware +#define I2S_AD_BCK_FACTOR (2) +#define I2S_PDM_BCK_FACTOR (64) +#define I2S_MAX_BUFFER_SIZE (4 * 1024 * 1024) //the maximum RAM can be allocated +#define I2S_BASE_CLK (2*APB_CLK_FREQ) + +// ESP32 have 2 I2S +#define I2S_NUM_0 (0) /*!< I2S port 0 */ +#define I2S_NUM_1 (1) /*!< I2S port 0 */ +#define I2S_NUM_MAX (2) /*!< I2S port max */ +#define SOC_I2S_NUM (I2S_NUM_MAX) + #define SOC_I2S_SUPPORT_PDM (1) //ESP32 support PDM + +#ifdef __cplusplus +} +#endif diff --git a/components/soc/esp32s2beta/i2s_periph.c b/components/soc/esp32s2beta/i2s_periph.c index 4e955ee06..5029a68c8 100644 --- a/components/soc/esp32s2beta/i2s_periph.c +++ b/components/soc/esp32s2beta/i2s_periph.c @@ -18,7 +18,7 @@ /* Bunch of constants for every I2S peripheral: GPIO signals, irqs, hw addr of registers etc */ -const i2s_signal_conn_t i2s_periph_signal[SOC_I2S_PERIPH_NUM] = { +const i2s_signal_conn_t i2s_periph_signal[SOC_I2S_NUM] = { { .o_bck_in_sig = I2S0O_BCK_IN_IDX, .o_ws_in_sig = I2S0O_WS_IN_IDX, diff --git a/components/soc/esp32s2beta/include/hal/i2s_ll.h b/components/soc/esp32s2beta/include/hal/i2s_ll.h new file mode 100644 index 000000000..fc760e35b --- /dev/null +++ b/components/soc/esp32s2beta/include/hal/i2s_ll.h @@ -0,0 +1,831 @@ +// Copyright 2015-2019 Espressif Systems (Shanghai) PTE LTD +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +/******************************************************************************* + * NOTICE + * The hal is not public api, don't use in application code. + * See readme.md in soc/include/hal/readme.md + ******************************************************************************/ + +// The LL layer for ESP32-S2 I2S register operations + +#pragma once + +#include +#include "soc/i2s_periph.h" +#include "hal/i2s_types.h" + +#ifdef __cplusplus +extern "C" { +#endif + +// Get I2S hardware instance with giving i2s num +#define I2S_LL_GET_HW(num) (((num) == 0) ? (&I2S0) : NULL) + +#define I2S_INTR_IN_SUC_EOF BIT(9) +#define I2S_INTR_OUT_EOF BIT(12) +#define I2S_INTR_IN_DSCR_ERR BIT(13) +#define I2S_INTR_OUT_DSCR_ERR BIT(14) +#define I2S_INTR_MAX (0xFFFFFFFF) + +/** + * @brief Reset rx fifo + * + * @param hw Peripheral I2S hardware instance address. + */ +static inline void i2s_ll_reset_rx_fifo(i2s_dev_t *hw) +{ + hw->conf.rx_fifo_reset = 1; + hw->conf.rx_fifo_reset = 0; +} + +/** + * @brief Reset tx fifo + * + * @param hw Peripheral I2S hardware instance address. + */ +static inline void i2s_ll_reset_tx_fifo(i2s_dev_t *hw) +{ + hw->conf.tx_fifo_reset = 1; + hw->conf.tx_fifo_reset = 0; +} + +/** + * @brief Enable rx interrupt + * + * @param hw Peripheral I2S hardware instance address. + */ +static inline void i2s_ll_enable_rx_intr(i2s_dev_t *hw) +{ + hw->int_ena.in_suc_eof = 1; + hw->int_ena.in_dscr_err = 1; +} + +/** + * @brief Disable rx interrupt + * + * @param hw Peripheral I2S hardware instance address. + */ +static inline void i2s_ll_disable_rx_intr(i2s_dev_t *hw) +{ + hw->int_ena.in_suc_eof = 0; + hw->int_ena.in_dscr_err = 0; +} + +/** + * @brief Disable tx interrupt + * + * @param hw Peripheral I2S hardware instance address. + */ +static inline void i2s_ll_disable_tx_intr(i2s_dev_t *hw) +{ + hw->int_ena.out_eof = 0; + hw->int_ena.out_dscr_err = 0; +} + +/** + * @brief Enable tx interrupt + * + * @param hw Peripheral I2S hardware instance address. + */ +static inline void i2s_ll_enable_tx_intr(i2s_dev_t *hw) +{ + hw->int_ena.out_eof = 1; + hw->int_ena.out_dscr_err = 1; +} + +/** + * @brief Reset dma in + * + * @param hw Peripheral I2S hardware instance address. + */ +static inline void i2s_ll_reset_dma_in(i2s_dev_t *hw) +{ + hw->lc_conf.in_rst = 1; + hw->lc_conf.in_rst = 0; +} + +/** + * @brief Reset dma out + * + * @param hw Peripheral I2S hardware instance address. + */ +static inline void i2s_ll_reset_dma_out(i2s_dev_t *hw) +{ + hw->lc_conf.out_rst = 1; + hw->lc_conf.out_rst = 0; +} + +/** + * @brief Reset tx + * + * @param hw Peripheral I2S hardware instance address. + */ +static inline void i2s_ll_reset_tx(i2s_dev_t *hw) +{ + hw->conf.tx_reset = 1; + hw->conf.tx_reset = 0; +} + +/** + * @brief Reset rx + * + * @param hw Peripheral I2S hardware instance address. + */ +static inline void i2s_ll_reset_rx(i2s_dev_t *hw) +{ + hw->conf.rx_reset = 1; + hw->conf.rx_reset = 0; +} + +/** + * @brief Start out link + * + * @param hw Peripheral I2S hardware instance address. + */ +static inline void i2s_ll_start_out_link(i2s_dev_t *hw) +{ + hw->out_link.start = 1; +} + +/** + * @brief Start tx + * + * @param hw Peripheral I2S hardware instance address. + */ +static inline void i2s_ll_start_tx(i2s_dev_t *hw) +{ + hw->conf.tx_start = 1; +} + +/** + * @brief Start in link + * + * @param hw Peripheral I2S hardware instance address. + */ +static inline void i2s_ll_start_in_link(i2s_dev_t *hw) +{ + hw->in_link.start = 1; +} + +/** + * @brief Start rx + * + * @param hw Peripheral I2S hardware instance address. + */ +static inline void i2s_ll_start_rx(i2s_dev_t *hw) +{ + hw->conf.rx_start = 1; +} + +/** + * @brief Stop out link + * + * @param hw Peripheral I2S hardware instance address. + */ +static inline void i2s_ll_stop_out_link(i2s_dev_t *hw) +{ + hw->out_link.stop = 1; +} + +/** + * @brief Stop tx + * + * @param hw Peripheral I2S hardware instance address. + */ +static inline void i2s_ll_stop_tx(i2s_dev_t *hw) +{ + hw->conf.tx_start = 0; +} + +/** + * @brief Stop in link + * + * @param hw Peripheral I2S hardware instance address. + */ +static inline void i2s_ll_stop_in_link(i2s_dev_t *hw) +{ + hw->in_link.stop = 1; +} + +/** + * @brief Stop rx + * + * @param hw Peripheral I2S hardware instance address. + */ +static inline void i2s_ll_stop_rx(i2s_dev_t *hw) +{ + hw->conf.rx_start = 0; +} + +/** + * @brief Enable dma + * + * @param hw Peripheral I2S hardware instance address. + */ +static inline void i2s_ll_enable_dma(i2s_dev_t *hw) +{ + //Enable and configure DMA + typeof(hw->lc_conf) lc_conf; + lc_conf.val = 0; + lc_conf.out_eof_mode = 1; + hw->lc_conf.val = lc_conf.val; +} + +/** + * @brief Get I2S revision + * + * @param hw Peripheral I2S hardware instance address. + * @param val value to get revision + */ +static inline void i2s_ll_get_rev(i2s_dev_t *hw, uint32_t *val) +{ + *val = 1; +} + +/** + * @brief Get I2S interrupt status + * + * @param hw Peripheral I2S hardware instance address. + * @param val value to get interrupt status + */ +static inline void i2s_ll_get_intr_status(i2s_dev_t *hw, uint32_t *val) +{ + *val = hw->int_st.val; +} + +/** + * @brief Clear I2S interrupt status + * + * @param hw Peripheral I2S hardware instance address. + * @param val value to clear interrupt status + */ +static inline void i2s_ll_clear_intr_status(i2s_dev_t *hw, uint32_t val) +{ + hw->int_clr.val = val; +} + +/** + * @brief Get I2S out eof des address + * + * @param hw Peripheral I2S hardware instance address. + * @param val value to get out eof des address + */ +static inline void i2s_ll_get_out_eof_des_addr(i2s_dev_t *hw, uint32_t *val) +{ + *val = hw->out_eof_des_addr; +} + +/** + * @brief Get I2S in eof des address + * + * @param hw Peripheral I2S hardware instance address. + * @param val value to get in eof des address + */ +static inline void i2s_ll_get_in_eof_des_addr(i2s_dev_t *hw, uint32_t *val) +{ + *val = hw->in_eof_des_addr; +} + +/** + * @brief Get I2S tx fifo mode + * + * @param hw Peripheral I2S hardware instance address. + * @param val value to get tx fifo mode + */ +static inline void i2s_ll_get_tx_fifo_mod(i2s_dev_t *hw, uint32_t *val) +{ + *val = hw->fifo_conf.tx_fifo_mod; +} + +/** + * @brief Set I2S tx fifo mode + * + * @param hw Peripheral I2S hardware instance address. + * @param val value to set tx fifo mode + */ +static inline void i2s_ll_set_tx_fifo_mod(i2s_dev_t *hw, uint32_t val) +{ + hw->fifo_conf.tx_fifo_mod = val; +} + +/** + * @brief Get I2S rx fifo mode + * + * @param hw Peripheral I2S hardware instance address. + * @param val value to get rx fifo mode + */ +static inline void i2s_ll_get_rx_fifo_mod(i2s_dev_t *hw, uint32_t *val) +{ + *val = hw->fifo_conf.rx_fifo_mod; +} + +/** + * @brief Set I2S rx fifo mode + * + * @param hw Peripheral I2S hardware instance address. + * @param val value to set rx fifo mode + */ +static inline void i2s_ll_set_rx_fifo_mod(i2s_dev_t *hw, uint32_t val) +{ + hw->fifo_conf.rx_fifo_mod = val; +} + +/** + * @brief Set I2S tx chan mode + * + * @param hw Peripheral I2S hardware instance address. + * @param val value to set tx chan mode + */ +static inline void i2s_ll_set_tx_chan_mod(i2s_dev_t *hw, uint32_t val) +{ + hw->conf_chan.tx_chan_mod = val; +} + +/** + * @brief Set I2S rx chan mode + * + * @param hw Peripheral I2S hardware instance address. + * @param val value to set rx chan mode + */ +static inline void i2s_ll_set_rx_chan_mod(i2s_dev_t *hw, uint32_t val) +{ + hw->conf_chan.rx_chan_mod = val; +} + +/** + * @brief Set I2S out link address + * + * @param hw Peripheral I2S hardware instance address. + * @param val value to set out link address + */ +static inline void i2s_ll_set_out_link_addr(i2s_dev_t *hw, uint32_t val) +{ + hw->out_link.addr = val; +} + +/** + * @brief Set I2S in link address + * + * @param hw Peripheral I2S hardware instance address. + * @param val value to set in link address + */ +static inline void i2s_ll_set_in_link_addr(i2s_dev_t *hw, uint32_t val) +{ + hw->in_link.addr = val; +} + +/** + * @brief Set I2S rx eof num + * + * @param hw Peripheral I2S hardware instance address. + * @param val value to set rx eof num + */ +static inline void i2s_ll_set_rx_eof_num(i2s_dev_t *hw, uint32_t val) +{ + hw->rx_eof_num = val; +} + +/** + * @brief Get I2S tx pdm fp + * + * @param hw Peripheral I2S hardware instance address. + * @param val value to get tx pdm fp + */ +static inline void i2s_ll_get_tx_pdm_fp(i2s_dev_t *hw, uint32_t *val) +{ + *val = hw->pdm_freq_conf.tx_pdm_fp; +} + +/** + * @brief Get I2S tx pdm fs + * + * @param hw Peripheral I2S hardware instance address. + * @param val value to get tx pdm fs + */ +static inline void i2s_ll_get_tx_pdm_fs(i2s_dev_t *hw, uint32_t *val) +{ + *val = hw->pdm_freq_conf.tx_pdm_fs; +} + +/** + * @brief Set I2S tx pdm fp + * + * @param hw Peripheral I2S hardware instance address. + * @param val value to set tx pdm fp + */ +static inline void i2s_ll_set_tx_pdm_fp(i2s_dev_t *hw, uint32_t val) +{ + hw->pdm_freq_conf.tx_pdm_fp = val; +} + +/** + * @brief Set I2S tx pdm fs + * + * @param hw Peripheral I2S hardware instance address. + * @param val value to set tx pdm fs + */ +static inline void i2s_ll_set_tx_pdm_fs(i2s_dev_t *hw, uint32_t val) +{ + hw->pdm_freq_conf.tx_pdm_fs = val; +} + +/** + * @brief Get I2S rx sinc dsr 16 en + * + * @param hw Peripheral I2S hardware instance address. + * @param val value to get rx sinc dsr 16 en + */ +static inline void i2s_ll_get_rx_sinc_dsr_16_en(i2s_dev_t *hw, bool *val) +{ + *val = hw->pdm_conf.rx_sinc_dsr_16_en; +} + +/** + * @brief Set I2S clkm div num + * + * @param hw Peripheral I2S hardware instance address. + * @param val value to set clkm div num + */ +static inline void i2s_ll_set_clkm_div_num(i2s_dev_t *hw, uint32_t val) +{ + hw->clkm_conf.clkm_div_num = val; +} + +/** + * @brief Set I2S clkm div b + * + * @param hw Peripheral I2S hardware instance address. + * @param val value to set clkm div b + */ +static inline void i2s_ll_set_clkm_div_b(i2s_dev_t *hw, uint32_t val) +{ + hw->clkm_conf.clkm_div_b = val; +} + +/** + * @brief Set I2S clkm div a + * + * @param hw Peripheral I2S hardware instance address. + * @param val value to set clkm div a + */ +static inline void i2s_ll_set_clkm_div_a(i2s_dev_t *hw, uint32_t val) +{ + hw->clkm_conf.clkm_div_a = val; +} + +/** + * @brief Set I2S tx bck div num + * + * @param hw Peripheral I2S hardware instance address. + * @param val value to set tx bck div num + */ +static inline void i2s_ll_set_tx_bck_div_num(i2s_dev_t *hw, uint32_t val) +{ + hw->sample_rate_conf.tx_bck_div_num = val; +} + +/** + * @brief Set I2S rx bck div num + * + * @param hw Peripheral I2S hardware instance address. + * @param val value to set rx bck div num + */ +static inline void i2s_ll_set_rx_bck_div_num(i2s_dev_t *hw, uint32_t val) +{ + hw->sample_rate_conf.rx_bck_div_num = val; +} + +/** + * @brief Set I2S clk sel + * + * @param hw Peripheral I2S hardware instance address. + * @param val value to set clk sel + */ +static inline void i2s_ll_set_clk_sel(i2s_dev_t *hw, uint32_t val) +{ + hw->clkm_conf.clk_sel = (val == 1) ? 1 : 2; +} + +/** + * @brief Set I2S tx bits mod + * + * @param hw Peripheral I2S hardware instance address. + * @param val value to set tx bits mod + */ +static inline void i2s_ll_set_tx_bits_mod(i2s_dev_t *hw, uint32_t val) +{ + hw->sample_rate_conf.tx_bits_mod = val; +} + +/** + * @brief Set I2S rx bits mod + * + * @param hw Peripheral I2S hardware instance address. + * @param val value to set rx bits mod + */ +static inline void i2s_ll_set_rx_bits_mod(i2s_dev_t *hw, uint32_t val) +{ + hw->sample_rate_conf.rx_bits_mod = val; +} + +/** + * @brief Set I2S rx sinc dsr 16 en + * + * @param hw Peripheral I2S hardware instance address. + * @param val value to set rx sinc dsr 16 en + */ +static inline void i2s_ll_set_rx_sinc_dsr_16_en(i2s_dev_t *hw, bool val) +{ + hw->pdm_conf.rx_sinc_dsr_16_en = val; +} + +/** + * @brief Set I2S dscr en + * + * @param hw Peripheral I2S hardware instance address. + * @param val value to set dscr en + */ +static inline void i2s_ll_set_dscr_en(i2s_dev_t *hw, bool val) +{ + hw->fifo_conf.dscr_en = val; +} + +/** + * @brief Set I2S lcd en + * + * @param hw Peripheral I2S hardware instance address. + * @param val value to set lcd en + */ +static inline void i2s_ll_set_lcd_en(i2s_dev_t *hw, bool val) +{ + hw->conf2.lcd_en = val; +} + +/** + * @brief Set I2S camera en + * + * @param hw Peripheral I2S hardware instance address. + * @param val value to set camera en + */ +static inline void i2s_ll_set_camera_en(i2s_dev_t *hw, bool val) +{ + hw->conf2.camera_en = val; +} + +/** + * @brief Set I2S pcm2pdm conv en + * + * @param hw Peripheral I2S hardware instance address. + * @param val value to set pcm2pdm conv en + */ +static inline void i2s_ll_set_pcm2pdm_conv_en(i2s_dev_t *hw, bool val) +{ + hw->pdm_conf.pcm2pdm_conv_en = val; +} + +/** + * @brief Set I2S pdm2pcm conv en + * + * @param hw Peripheral I2S hardware instance address. + * @param val value to set pdm2pcm conv en + */ +static inline void i2s_ll_set_pdm2pcm_conv_en(i2s_dev_t *hw, bool val) +{ + hw->pdm_conf.pdm2pcm_conv_en = val; +} + +/** + * @brief Set I2S rx pdm en + * + * @param hw Peripheral I2S hardware instance address. + * @param val value to set rx pdm en + */ +static inline void i2s_ll_set_rx_pdm_en(i2s_dev_t *hw, bool val) +{ + hw->pdm_conf.rx_pdm_en = val; +} + +/** + * @brief Set I2S tx pdm en + * + * @param hw Peripheral I2S hardware instance address. + * @param val value to set tx pdm en + */ +static inline void i2s_ll_set_tx_pdm_en(i2s_dev_t *hw, bool val) +{ + hw->pdm_conf.tx_pdm_en = val; +} + +/** + * @brief Set I2S tx msb shift + * + * @param hw Peripheral I2S hardware instance address. + * @param val value to set tx msb shift + */ +static inline void i2s_ll_set_tx_msb_shift(i2s_dev_t *hw, uint32_t val) +{ + hw->conf.tx_msb_shift = val; +} + +/** + * @brief Set I2S rx msb shift + * + * @param hw Peripheral I2S hardware instance address. + * @param val value to set rx msb shift + */ +static inline void i2s_ll_set_rx_msb_shift(i2s_dev_t *hw, uint32_t val) +{ + hw->conf.rx_msb_shift = val; +} + +/** + * @brief Set I2S tx short sync + * + * @param hw Peripheral I2S hardware instance address. + * @param val value to set tx short sync + */ +static inline void i2s_ll_set_tx_short_sync(i2s_dev_t *hw, uint32_t val) +{ + hw->conf.tx_short_sync = val; +} + +/** + * @brief Set I2S rx short sync + * + * @param hw Peripheral I2S hardware instance address. + * @param val value to set rx short sync + */ +static inline void i2s_ll_set_rx_short_sync(i2s_dev_t *hw, uint32_t val) +{ + hw->conf.rx_short_sync = val; +} + +/** + * @brief Set I2S tx fifo mod force en + * + * @param hw Peripheral I2S hardware instance address. + * @param val value to set tx fifo mod force en + */ +static inline void i2s_ll_set_tx_fifo_mod_force_en(i2s_dev_t *hw, bool val) +{ + hw->fifo_conf.tx_fifo_mod_force_en = val; +} + +/** + * @brief Set I2S rx fifo mod force en + * + * @param hw Peripheral I2S hardware instance address. + * @param val value to set rx fifo mod force en + */ +static inline void i2s_ll_set_rx_fifo_mod_force_en(i2s_dev_t *hw, bool val) +{ + hw->fifo_conf.rx_fifo_mod_force_en = val; +} + +/** + * @brief Set I2S tx right first + * + * @param hw Peripheral I2S hardware instance address. + * @param val value to set tx right first + */ +static inline void i2s_ll_set_tx_right_first(i2s_dev_t *hw, uint32_t val) +{ + hw->conf.tx_right_first = val; +} + +/** + * @brief Set I2S rx right first + * + * @param hw Peripheral I2S hardware instance address. + * @param val value to set rx right first + */ +static inline void i2s_ll_set_rx_right_first(i2s_dev_t *hw, uint32_t val) +{ + hw->conf.rx_right_first = val; +} + +/** + * @brief Set I2S tx slave mod + * + * @param hw Peripheral I2S hardware instance address. + * @param val value to set tx slave mod + */ +static inline void i2s_ll_set_tx_slave_mod(i2s_dev_t *hw, uint32_t val) +{ + hw->conf.tx_slave_mod = val; +} + +/** + * @brief Set I2S rx slave mod + * + * @param hw Peripheral I2S hardware instance address. + * @param val value to set rx slave mod + */ +static inline void i2s_ll_set_rx_slave_mod(i2s_dev_t *hw, uint32_t val) +{ + hw->conf.rx_slave_mod = val; +} + +/** + * @brief Get I2S tx msb right + * + * @param hw Peripheral I2S hardware instance address. + * @param val value to get tx msb right + */ +static inline void i2s_ll_get_tx_msb_right(i2s_dev_t *hw, uint32_t *val) +{ + *val = hw->conf.tx_msb_right; +} + +/** + * @brief Get I2S rx msb right + * + * @param hw Peripheral I2S hardware instance address. + * @param val value to get rx msb right + */ +static inline void i2s_ll_get_rx_msb_right(i2s_dev_t *hw, uint32_t *val) +{ + *val = hw->conf.rx_msb_right; +} + +/** + * @brief Set I2S tx msb right + * + * @param hw Peripheral I2S hardware instance address. + * @param val value to set tx msb right + */ +static inline void i2s_ll_set_tx_msb_right(i2s_dev_t *hw, uint32_t val) +{ + hw->conf.tx_msb_right = val; +} + +/** + * @brief Set I2S rx msb right + * + * @param hw Peripheral I2S hardware instance address. + * @param val value to set rx msb right + */ +static inline void i2s_ll_set_rx_msb_right(i2s_dev_t *hw, uint32_t val) +{ + hw->conf.rx_msb_right = val; +} + +/** + * @brief Set I2S tx mono + * + * @param hw Peripheral I2S hardware instance address. + * @param val value to set tx mono + */ +static inline void i2s_ll_set_tx_mono(i2s_dev_t *hw, uint32_t val) +{ + hw->conf.tx_mono = val; +} + +/** + * @brief Set I2S rx mono + * + * @param hw Peripheral I2S hardware instance address. + * @param val value to set rx mono + */ +static inline void i2s_ll_set_rx_mono(i2s_dev_t *hw, uint32_t val) +{ + hw->conf.rx_mono = val; +} + +/** + * @brief Set I2S tx sinc osr2 + * + * @param hw Peripheral I2S hardware instance address. + * @param val value to set tx sinc osr2 + */ +static inline void i2s_ll_set_tx_sinc_osr2(i2s_dev_t *hw, uint32_t val) +{ + hw->pdm_conf.tx_sinc_osr2 = val; +} + +/** + * @brief Set I2S sig loopback + * + * @param hw Peripheral I2S hardware instance address. + * @param val value to set sig loopback + */ +static inline void i2s_ll_set_sig_loopback(i2s_dev_t *hw, uint32_t val) +{ + hw->conf.sig_loopback = val; +} + +#ifdef __cplusplus +} +#endif \ No newline at end of file diff --git a/components/soc/esp32s2beta/include/soc/i2s_caps.h b/components/soc/esp32s2beta/include/soc/i2s_caps.h index 9dfa5bb6d..0b5eab036 100644 --- a/components/soc/esp32s2beta/include/soc/i2s_caps.h +++ b/components/soc/esp32s2beta/include/soc/i2s_caps.h @@ -14,5 +14,17 @@ #pragma once -#define SOC_I2S_PERIPH_NUM (1) //ESP32-S2 have 1 I2S -#define SOC_I2S_SUPPORT_PDM (0) //ESP32-S2 do not support PDM +#define APLL_MIN_FREQ (250000000) +#define APLL_MAX_FREQ (500000000) +#define APLL_I2S_MIN_RATE (10675) //in Hz, I2S Clock rate limited by hardware +#define I2S_AD_BCK_FACTOR (2) +#define I2S_PDM_BCK_FACTOR (64) +#define I2S_MAX_BUFFER_SIZE (4 * 1024 * 1024) //the maximum RAM can be allocated +#define I2S_BASE_CLK (2*APB_CLK_FREQ) + +// ESP32-S2 have 2 I2S +#define I2S_NUM_0 (0) /*!< I2S port 0 */ +#define I2S_NUM_MAX (1) /*!< I2S port max */ +#define SOC_I2S_NUM (I2S_NUM_MAX) + +#define SOC_I2S_SUPPORT_PDM (0) // ESP32-S2 do not support PDM diff --git a/components/soc/include/hal/i2s_hal.h b/components/soc/include/hal/i2s_hal.h new file mode 100644 index 000000000..24cab0d98 --- /dev/null +++ b/components/soc/include/hal/i2s_hal.h @@ -0,0 +1,304 @@ +// Copyright 2015-2019 Espressif Systems (Shanghai) PTE LTD +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +/******************************************************************************* + * NOTICE + * The hal is not public api, don't use in application code. + * See readme.md in soc/include/hal/readme.md + ******************************************************************************/ + +// The HAL layer for I2S. +// There is no parameter check in the hal layer, so the caller must ensure the correctness of the parameters. + +#pragma once + +#include "soc/i2s_periph.h" +#include "soc/i2s_caps.h" +#include "hal/i2s_ll.h" +#include "hal/i2s_types.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * Context that should be maintained by both the driver and the HAL + */ +typedef struct { + i2s_dev_t *dev; + uint32_t version; +} i2s_hal_context_t; + +/** + * @brief Reset I2S fifo + * + * @param hal Context of the HAL layer + */ +void i2s_hal_reset_fifo(i2s_hal_context_t *hal); + +/** + * @brief Get I2S revision + * + * @param hal Context of the HAL layer + * @param rev I2S revision + */ +#define i2s_hal_get_rev(hal, rev) i2s_ll_get_rev((hal)->dev, rev) + +/** + * @brief Get I2S interrupt status + * + * @param hal Context of the HAL layer + * @param status interrupt status + */ +#define i2s_hal_get_intr_status(hal, status) i2s_ll_get_intr_status((hal)->dev, status) + +/** + * @brief Clear I2S interrupt status + * + * @param hal Context of the HAL layer + * @param mask interrupt status mask + */ +#define i2s_hal_clear_intr_status(hal, mask) i2s_ll_clear_intr_status((hal)->dev, mask) + +/** + * @brief Get I2S out eof des address + * + * @param hal Context of the HAL layer + * @param addr out eof des address + */ +#define i2s_hal_get_out_eof_des_addr(hal, addr) i2s_ll_get_out_eof_des_addr((hal)->dev, addr) + +/** + * @brief Get I2S in eof des address + * + * @param hal Context of the HAL layer + * @param addr in eof des address + */ +#define i2s_hal_get_in_eof_des_addr(hal, addr) i2s_ll_get_in_eof_des_addr((hal)->dev, addr) + +/** + * @brief Enable I2S rx interrupt + * + * @param hal Context of the HAL layer + */ +#define i2s_hal_enable_rx_intr(hal) i2s_ll_enable_rx_intr((hal)->dev) + +/** + * @brief Disable I2S rx interrupt + * + * @param hal Context of the HAL layer + */ +#define i2s_hal_disable_rx_intr(hal) i2s_ll_disable_rx_intr((hal)->dev) + +/** + * @brief Disable I2S tx interrupt + * + * @param hal Context of the HAL layer + */ +#define i2s_hal_disable_tx_intr(hal) i2s_ll_disable_tx_intr((hal)->dev) + +/** + * @brief Enable I2S tx interrupt + * + * @param hal Context of the HAL layer + */ +#define i2s_hal_enable_tx_intr(hal) i2s_ll_enable_tx_intr((hal)->dev) + +/** + * @brief Set I2S tx mode + * + * @param hal Context of the HAL layer + * @param ch i2s channel + * @param bits bits per sample + */ +void i2s_hal_set_tx_mode(i2s_hal_context_t *hal, i2s_channel_t ch, i2s_bits_per_sample_t bits); + +/** + * @brief Set I2S rx mode + * + * @param hal Context of the HAL layer + * @param ch i2s channel + * @param bits bits per sample + */ +void i2s_hal_set_rx_mode(i2s_hal_context_t *hal, i2s_channel_t ch, i2s_bits_per_sample_t bits); + +/** + * @brief Set I2S out link address + * + * @param hal Context of the HAL layer + * @param addr out link address + */ +#define i2s_hal_set_out_link_addr(hal, addr) i2s_ll_set_out_link_addr((hal)->dev, addr) + +/** + * @brief Set I2S out link address + * + * @param hal Context of the HAL layer + * @param addr out link address + */ +#define i2s_hal_set_out_link_addr(hal, addr) i2s_ll_set_out_link_addr((hal)->dev, addr) + +/** + * @brief Set I2S out link address + * + * @param hal Context of the HAL layer + * @param addr out link address + */ +#define i2s_hal_set_out_link_addr(hal, addr) i2s_ll_set_out_link_addr((hal)->dev, addr) + +/** + * @brief Set I2S in link + * + * @param hal Context of the HAL layer + * @param rx_eof_num in link eof num + * @param addr in link address + */ +void i2s_hal_set_in_link(i2s_hal_context_t *hal, uint32_t rx_eof_num, uint32_t addr); + +/** + * @brief Get I2S tx pdm + * + * @param hal Context of the HAL layer + * @param fp tx pdm fp + * @param fs tx pdm fs + */ +void i2s_hal_get_tx_pdm(i2s_hal_context_t *hal, int *fp, int *fs); + +/** + * @brief Get I2S rx sinc dsr 16 en + * + * @param hal Context of the HAL layer + * @param en 0: disable, 1: enable + */ +#define i2s_hal_get_rx_sinc_dsr_16_en(hal, en) i2s_ll_get_rx_sinc_dsr_16_en((hal)->dev, en) + +/** + * @brief Set I2S clk div + * + * @param hal Context of the HAL layer + * @param div_num i2s clkm div num + * @param div_a i2s clkm div a + * @param div_b i2s clkm div b + * @param tx_bck_div tx bck div num + * @param rx_bck_div rx bck div num + */ +void i2s_hal_set_clk_div(i2s_hal_context_t *hal, int div_num, int div_a, int div_b, int tx_bck_div, int rx_bck_div); + +/** + * @brief Set I2S clock sel + * + * @param hal Context of the HAL layer + * @param sel clock sel + */ +#define i2s_hal_set_clock_sel(hal, sel) i2s_ll_set_clk_sel((hal)->dev, sel) + +/** + * @brief Set I2S tx bits mod + * + * @param hal Context of the HAL layer + * @param bits bit width per sample. + */ +void i2s_hal_set_tx_bits_mod(i2s_hal_context_t *hal, i2s_bits_per_sample_t bits); + +/** + * @brief Set I2S rx bits mod + * + * @param hal Context of the HAL layer + * @param bits bit width per sample. + */ +void i2s_hal_set_rx_bits_mod(i2s_hal_context_t *hal, i2s_bits_per_sample_t bits); + +/** + * @brief Reset I2S tx + * + * @param hal Context of the HAL layer + */ +void i2s_hal_reset(i2s_hal_context_t *hal); + +/** + * @brief Start I2S tx + * + * @param hal Context of the HAL layer + */ +void i2s_hal_start_tx(i2s_hal_context_t *hal); + +/** + * @brief Start I2S rx + * + * @param hal Context of the HAL layer + */ +void i2s_hal_start_rx(i2s_hal_context_t *hal); + +/** + * @brief Stop I2S tx + * + * @param hal Context of the HAL layer + */ +void i2s_hal_stop_tx(i2s_hal_context_t *hal); + +/** + * @brief Stop I2S rx + * + * @param hal Context of the HAL layer + */ +void i2s_hal_stop_rx(i2s_hal_context_t *hal); + +/** + * @brief Set I2S pdm rx down sample + * + * @param hal Context of the HAL layer + * @param dsr 0:disable, 1: enable + */ +#define i2s_hal_set_pdm_rx_down_sample(hal, dsr) i2s_ll_set_rx_sinc_dsr_16_en((hal)->dev, dsr) + +/** + * @brief Config I2S param + * + * @param hal Context of the HAL layer + * @param i2s_config I2S configurations - see i2s_config_t struct + */ +void i2s_hal_config_param(i2s_hal_context_t *hal, const i2s_config_t *i2s_config); + +/** + * @brief Enable I2S sig loopback + * + * @param hal Context of the HAL layer + */ +#define i2s_hal_enable_sig_loopback(hal) i2s_ll_set_sig_loopback((hal)->dev, 1) + +/** + * @brief Enable I2S master mode + * + * @param hal Context of the HAL layer + */ +void i2s_hal_enable_master_mode(i2s_hal_context_t *hal); + +/** + * @brief Enable I2S slave mode + * + * @param hal Context of the HAL layer + */ +void i2s_hal_enable_slave_mode(i2s_hal_context_t *hal); + +/** + * @brief Init the I2S hal and set the I2S to the default configuration. This function should be called first before other hal layer function is called + * + * @param hal Context of the HAL layer + * @param i2s_num The uart port number, the max port number is (I2S_NUM_MAX -1) + */ +void i2s_hal_init(i2s_hal_context_t *hal, int i2s_num); + +#ifdef __cplusplus +} +#endif \ No newline at end of file diff --git a/components/soc/include/hal/i2s_types.h b/components/soc/include/hal/i2s_types.h new file mode 100644 index 000000000..471d105fe --- /dev/null +++ b/components/soc/include/hal/i2s_types.h @@ -0,0 +1,195 @@ +// Copyright 2015-2019 Espressif Systems (Shanghai) PTE LTD +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#pragma once + +#include +#include +#include +#include "soc/i2s_caps.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * @brief I2S port number, the max port number is (I2S_NUM_MAX -1). + */ +typedef int i2s_port_t; + +#define I2S_PIN_NO_CHANGE (-1) /*!< Use in i2s_pin_config_t for pins which should not be changed */ + +/** + * @brief I2S bit width per sample. + * + */ +typedef enum { + I2S_BITS_PER_SAMPLE_8BIT = 8, /*!< I2S bits per sample: 8-bits*/ + I2S_BITS_PER_SAMPLE_16BIT = 16, /*!< I2S bits per sample: 16-bits*/ + I2S_BITS_PER_SAMPLE_24BIT = 24, /*!< I2S bits per sample: 24-bits*/ + I2S_BITS_PER_SAMPLE_32BIT = 32, /*!< I2S bits per sample: 32-bits*/ +} i2s_bits_per_sample_t; + +/** + * @brief I2S channel. + * + */ +typedef enum { + I2S_CHANNEL_MONO = 1, /*!< I2S 1 channel (mono)*/ + I2S_CHANNEL_STEREO = 2 /*!< I2S 2 channel (stereo)*/ +} i2s_channel_t; + +/** + * @brief I2S communication standard format + * + */ +typedef enum { + I2S_COMM_FORMAT_I2S = 0x01, /*!< I2S communication format I2S*/ + I2S_COMM_FORMAT_I2S_MSB = 0x02, /*!< I2S format MSB*/ + I2S_COMM_FORMAT_I2S_LSB = 0x04, /*!< I2S format LSB*/ + I2S_COMM_FORMAT_PCM = 0x08, /*!< I2S communication format PCM*/ + I2S_COMM_FORMAT_PCM_SHORT = 0x10, /*!< PCM Short*/ + I2S_COMM_FORMAT_PCM_LONG = 0x20, /*!< PCM Long*/ +} i2s_comm_format_t; + + +/** + * @brief I2S channel format type + */ +typedef enum { + I2S_CHANNEL_FMT_RIGHT_LEFT = 0x00, + I2S_CHANNEL_FMT_ALL_RIGHT, + I2S_CHANNEL_FMT_ALL_LEFT, + I2S_CHANNEL_FMT_ONLY_RIGHT, + I2S_CHANNEL_FMT_ONLY_LEFT, +} i2s_channel_fmt_t; + +/** + * @brief PDM sample rate ratio, measured in Hz. + * + */ +typedef enum { + PDM_SAMPLE_RATE_RATIO_64, + PDM_SAMPLE_RATE_RATIO_128, +} pdm_sample_rate_ratio_t; + +/** + * @brief PDM PCM convter enable/disable. + * + */ +typedef enum { + PDM_PCM_CONV_ENABLE, + PDM_PCM_CONV_DISABLE, +} pdm_pcm_conv_t; + +/** + * @brief I2S Mode, defaut is I2S_MODE_MASTER | I2S_MODE_TX + * + * @note PDM and built-in DAC functions are only supported on I2S0 for current ESP32 chip. + * + */ +typedef enum { + I2S_MODE_MASTER = 1, + I2S_MODE_SLAVE = 2, + I2S_MODE_TX = 4, + I2S_MODE_RX = 8, + I2S_MODE_DAC_BUILT_IN = 16, /*!< Output I2S data to built-in DAC, no matter the data format is 16bit or 32 bit, the DAC module will only take the 8bits from MSB*/ + I2S_MODE_ADC_BUILT_IN = 32, /*!< Input I2S data from built-in ADC, each data can be 12-bit width at most*/ +#if SOC_I2S_SUPPORT_PDM + I2S_MODE_PDM = 64, +#endif +} i2s_mode_t; + +/** + * @brief I2S configuration parameters for i2s_param_config function + * + */ +typedef struct { + i2s_mode_t mode; /*!< I2S work mode*/ + int sample_rate; /*!< I2S sample rate*/ + i2s_bits_per_sample_t bits_per_sample; /*!< I2S bits per sample*/ + i2s_channel_fmt_t channel_format; /*!< I2S channel format */ + i2s_comm_format_t communication_format; /*!< I2S communication format */ + int intr_alloc_flags; /*!< Flags used to allocate the interrupt. One or multiple (ORred) ESP_INTR_FLAG_* values. See esp_intr_alloc.h for more info */ + int dma_buf_count; /*!< I2S DMA Buffer Count */ + int dma_buf_len; /*!< I2S DMA Buffer Length */ + bool use_apll; /*!< I2S using APLL as main I2S clock, enable it to get accurate clock */ + bool tx_desc_auto_clear; /*!< I2S auto clear tx descriptor if there is underflow condition (helps in avoiding noise in case of data unavailability) */ + int fixed_mclk; /*!< I2S using fixed MCLK output. If use_apll = true and fixed_mclk > 0, then the clock output for i2s is fixed and equal to the fixed_mclk value.*/ +} i2s_config_t; + +/** + * @brief I2S event types + * + */ +typedef enum { + I2S_EVENT_DMA_ERROR, + I2S_EVENT_TX_DONE, /*!< I2S DMA finish sent 1 buffer*/ + I2S_EVENT_RX_DONE, /*!< I2S DMA finish received 1 buffer*/ + I2S_EVENT_MAX, /*!< I2S event max index*/ +} i2s_event_type_t; + +/** + * @brief I2S DAC mode for i2s_set_dac_mode. + * + * @note PDM and built-in DAC functions are only supported on I2S0 for current ESP32 chip. + */ +typedef enum { + I2S_DAC_CHANNEL_DISABLE = 0, /*!< Disable I2S built-in DAC signals*/ + I2S_DAC_CHANNEL_RIGHT_EN = 1, /*!< Enable I2S built-in DAC right channel, maps to DAC channel 1 on GPIO25*/ + I2S_DAC_CHANNEL_LEFT_EN = 2, /*!< Enable I2S built-in DAC left channel, maps to DAC channel 2 on GPIO26*/ + I2S_DAC_CHANNEL_BOTH_EN = 0x3, /*!< Enable both of the I2S built-in DAC channels.*/ + I2S_DAC_CHANNEL_MAX = 0x4, /*!< I2S built-in DAC mode max index*/ +} i2s_dac_mode_t; + +/** + * @brief Event structure used in I2S event queue + * + */ +typedef struct { + i2s_event_type_t type; /*!< I2S event type */ + size_t size; /*!< I2S data size for I2S_DATA event*/ +} i2s_event_t; + +/** + * @brief I2S pin number for i2s_set_pin + * + */ +typedef struct { + int bck_io_num; /*!< BCK in out pin*/ + int ws_io_num; /*!< WS in out pin*/ + int data_out_num; /*!< DATA out pin*/ + int data_in_num; /*!< DATA in pin*/ +} i2s_pin_config_t; + +#if SOC_I2S_SUPPORT_PDM +/** + * @brief I2S PDM RX downsample mode + */ +typedef enum { + I2S_PDM_DSR_8S = 0, /*!< downsampling number is 8 for PDM RX mode*/ + I2S_PDM_DSR_16S, /*!< downsampling number is 16 for PDM RX mode*/ + I2S_PDM_DSR_MAX, +} i2s_pdm_dsr_t; +#endif + +typedef enum { + I2S_CLK_D2CLK = 0, + I2S_CLK_APLL, +} i2s_clock_src_t; + + +#ifdef __cplusplus +} +#endif \ No newline at end of file diff --git a/components/soc/include/soc/i2s_periph.h b/components/soc/include/soc/i2s_periph.h index 0c6e003ad..df72723a2 100644 --- a/components/soc/include/soc/i2s_periph.h +++ b/components/soc/include/soc/i2s_periph.h @@ -41,7 +41,7 @@ typedef struct { const periph_module_t module; } i2s_signal_conn_t; -extern const i2s_signal_conn_t i2s_periph_signal[SOC_I2S_PERIPH_NUM]; +extern const i2s_signal_conn_t i2s_periph_signal[SOC_I2S_NUM]; #ifdef __cplusplus } diff --git a/components/soc/src/hal/i2s_hal.c b/components/soc/src/hal/i2s_hal.c new file mode 100644 index 000000000..6639525ea --- /dev/null +++ b/components/soc/src/hal/i2s_hal.c @@ -0,0 +1,244 @@ +// Copyright 2015-2019 Espressif Systems (Shanghai) PTE LTD +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +// The HAL layer for I2S (common part) + +#include "soc/soc.h" +#include "esp_log.h" +#include "hal/i2s_hal.h" + +void i2s_hal_reset_fifo(i2s_hal_context_t *hal) +{ + i2s_ll_reset_rx_fifo(hal->dev); + i2s_ll_reset_tx_fifo(hal->dev); +} + +void i2s_hal_set_tx_mode(i2s_hal_context_t *hal, i2s_channel_t ch, i2s_bits_per_sample_t bits) +{ + if (bits <= I2S_BITS_PER_SAMPLE_16BIT) { + i2s_ll_set_tx_fifo_mod(hal->dev, (ch == I2S_CHANNEL_STEREO) ? 0 : 1); + } else { + i2s_ll_set_tx_fifo_mod(hal->dev, (ch == I2S_CHANNEL_STEREO) ? 2 : 3); + } + i2s_ll_set_tx_chan_mod(hal->dev, (ch == I2S_CHANNEL_STEREO) ? 0 : 1); +} + +void i2s_hal_set_rx_mode(i2s_hal_context_t *hal, i2s_channel_t ch, i2s_bits_per_sample_t bits) +{ + if (bits <= I2S_BITS_PER_SAMPLE_16BIT) { + i2s_ll_set_rx_fifo_mod(hal->dev, (ch == I2S_CHANNEL_STEREO) ? 0 : 1); + } else { + i2s_ll_set_rx_fifo_mod(hal->dev, (ch == I2S_CHANNEL_STEREO) ? 2 : 3); + } + i2s_ll_set_rx_chan_mod(hal->dev, (ch == I2S_CHANNEL_STEREO) ? 0 : 1); +} + +void i2s_hal_set_in_link(i2s_hal_context_t *hal, uint32_t bytes_num, uint32_t addr) +{ + i2s_ll_set_in_link_addr(hal->dev, addr); + i2s_ll_set_rx_eof_num(hal->dev, bytes_num); +} + +void i2s_hal_get_tx_pdm(i2s_hal_context_t *hal, int *fp, int *fs) +{ + i2s_ll_get_tx_pdm_fp(hal->dev, (uint32_t *)fp); + i2s_ll_get_tx_pdm_fs(hal->dev, (uint32_t *)fs); +} + +void i2s_hal_set_clk_div(i2s_hal_context_t *hal, int div_num, int div_a, int div_b, int tx_bck_div, int rx_bck_div) +{ + i2s_ll_set_clkm_div_num(hal->dev, div_num); + i2s_ll_set_clkm_div_a(hal->dev, div_a); + i2s_ll_set_clkm_div_b(hal->dev, div_b); + i2s_ll_set_tx_bck_div_num(hal->dev, tx_bck_div); + i2s_ll_set_rx_bck_div_num(hal->dev, rx_bck_div); +} + +void i2s_hal_set_tx_bits_mod(i2s_hal_context_t *hal, i2s_bits_per_sample_t bits) +{ + i2s_ll_set_tx_bits_mod(hal->dev, bits); +} + +void i2s_hal_set_rx_bits_mod(i2s_hal_context_t *hal, i2s_bits_per_sample_t bits) +{ + i2s_ll_set_rx_bits_mod(hal->dev, bits); +} + +void i2s_hal_reset(i2s_hal_context_t *hal) +{ + i2s_ll_reset_dma_in(hal->dev); + i2s_ll_reset_dma_out(hal->dev); + i2s_ll_reset_tx(hal->dev); + i2s_ll_reset_rx(hal->dev); +} + +void i2s_hal_start_tx(i2s_hal_context_t *hal) +{ + i2s_ll_start_out_link(hal->dev); + i2s_ll_start_tx(hal->dev); +} + +void i2s_hal_start_rx(i2s_hal_context_t *hal) +{ + i2s_ll_start_in_link(hal->dev); + i2s_ll_start_rx(hal->dev); +} + +void i2s_hal_stop_tx(i2s_hal_context_t *hal) +{ + i2s_ll_stop_out_link(hal->dev); + i2s_ll_stop_tx(hal->dev); +} + +void i2s_hal_stop_rx(i2s_hal_context_t *hal) +{ + i2s_ll_stop_in_link(hal->dev); + i2s_ll_stop_rx(hal->dev); +} + +void i2s_hal_config_param(i2s_hal_context_t *hal, const i2s_config_t *i2s_config) +{ + //reset i2s + i2s_ll_reset_tx(hal->dev); + i2s_ll_reset_rx(hal->dev); + + //reset dma + i2s_ll_reset_dma_in(hal->dev); + i2s_ll_reset_dma_out(hal->dev); + + i2s_ll_enable_dma(hal->dev); + + i2s_ll_set_lcd_en(hal->dev, 0); + i2s_ll_set_camera_en(hal->dev, 0); + i2s_ll_set_pcm2pdm_conv_en(hal->dev, 0); + i2s_ll_set_pdm2pcm_conv_en(hal->dev, 0); + + i2s_ll_set_dscr_en(hal->dev, 0); + + i2s_ll_set_tx_chan_mod(hal->dev, i2s_config->channel_format < I2S_CHANNEL_FMT_ONLY_RIGHT ? i2s_config->channel_format : (i2s_config->channel_format >> 1)); // 0-two channel;1-right;2-left;3-righ;4-left + i2s_ll_set_tx_fifo_mod(hal->dev, i2s_config->channel_format < I2S_CHANNEL_FMT_ONLY_RIGHT ? 0 : 1); // 0-right&left channel;1-one channel + i2s_ll_set_tx_mono(hal->dev, 0); + + i2s_ll_set_rx_chan_mod(hal->dev, i2s_config->channel_format < I2S_CHANNEL_FMT_ONLY_RIGHT ? i2s_config->channel_format : (i2s_config->channel_format >> 1)); // 0-two channel;1-right;2-left;3-righ;4-left + i2s_ll_set_rx_fifo_mod(hal->dev, i2s_config->channel_format < I2S_CHANNEL_FMT_ONLY_RIGHT ? 0 : 1); // 0-right&left channel;1-one channel + i2s_ll_set_rx_mono(hal->dev, 0); + + i2s_ll_set_dscr_en(hal->dev, 1); //connect dma to fifo + + i2s_ll_stop_tx(hal->dev); + i2s_ll_stop_rx(hal->dev); + + if (i2s_config->mode & I2S_MODE_TX) { + i2s_ll_set_tx_msb_right(hal->dev, 0); + i2s_ll_set_tx_right_first(hal->dev, 0); + + i2s_ll_set_tx_slave_mod(hal->dev, 0); // Master + i2s_ll_set_tx_fifo_mod_force_en(hal->dev, 1); + + if (i2s_config->mode & I2S_MODE_SLAVE) { + i2s_ll_set_tx_slave_mod(hal->dev, 1); //TX Slave + } + } + + if (i2s_config->mode & I2S_MODE_RX) { + i2s_ll_set_rx_msb_right(hal->dev, 0); + i2s_ll_set_rx_right_first(hal->dev, 0); + i2s_ll_set_rx_slave_mod(hal->dev, 0); // Master + i2s_ll_set_rx_fifo_mod_force_en(hal->dev, 1); + + if (i2s_config->mode & I2S_MODE_SLAVE) { + i2s_ll_set_rx_slave_mod(hal->dev, 1); //RX Slave + } + } + + if (i2s_config->mode & (I2S_MODE_DAC_BUILT_IN | I2S_MODE_ADC_BUILT_IN)) { + i2s_ll_set_lcd_en(hal->dev, 1); + i2s_ll_set_tx_right_first(hal->dev, 1); + i2s_ll_set_camera_en(hal->dev, 0); + } + +#if SOC_I2S_SUPPORT_PDM + if (i2s_config->mode & I2S_MODE_PDM) { + i2s_ll_set_rx_fifo_mod_force_en(hal->dev, 1); + i2s_ll_set_tx_fifo_mod_force_en(hal->dev, 1); + + i2s_ll_set_tx_pdm_fp(hal->dev, 960); + i2s_ll_set_tx_pdm_fs(hal->dev, i2s_config->sample_rate / 1000 * 10); + uint32_t fp, fs; + i2s_ll_get_tx_pdm_fp(hal->dev, &fp); + i2s_ll_get_tx_pdm_fs(hal->dev, &fs); + i2s_ll_set_tx_sinc_osr2(hal->dev, fp / fs); + + i2s_ll_set_rx_sinc_dsr_16_en(hal->dev, 0); + i2s_ll_set_rx_pdm_en(hal->dev, 1); + i2s_ll_set_tx_pdm_en(hal->dev, 1); + + i2s_ll_set_pcm2pdm_conv_en(hal->dev, 1); + i2s_ll_set_pdm2pcm_conv_en(hal->dev, 1); + } else { + i2s_ll_set_rx_pdm_en(hal->dev, 0); + i2s_ll_set_tx_pdm_en(hal->dev, 0); + } +#else + i2s_ll_set_rx_pdm_en(hal->dev, 0); + i2s_ll_set_tx_pdm_en(hal->dev, 0); +#endif + if (i2s_config->communication_format & I2S_COMM_FORMAT_I2S || i2s_config->communication_format & I2S_COMM_FORMAT_I2S_MSB || i2s_config->communication_format & I2S_COMM_FORMAT_I2S_LSB) { + i2s_ll_set_tx_short_sync(hal->dev, 0); + i2s_ll_set_rx_short_sync(hal->dev, 0); + i2s_ll_set_tx_msb_shift(hal->dev, 1); + i2s_ll_set_rx_msb_shift(hal->dev, 1); + if (i2s_config->communication_format & I2S_COMM_FORMAT_I2S_LSB) { + if (i2s_config->mode & I2S_MODE_TX) { + i2s_ll_set_tx_msb_shift(hal->dev, 0); + } + if (i2s_config->mode & I2S_MODE_RX) { + i2s_ll_set_rx_msb_shift(hal->dev, 0); + } + } + } + + if (i2s_config->communication_format & I2S_COMM_FORMAT_PCM || i2s_config->communication_format & I2S_COMM_FORMAT_PCM_LONG || i2s_config->communication_format & I2S_COMM_FORMAT_PCM_SHORT) { + i2s_ll_set_tx_msb_shift(hal->dev, 0); + i2s_ll_set_rx_msb_shift(hal->dev, 0); + i2s_ll_set_tx_short_sync(hal->dev, 0); + i2s_ll_set_rx_short_sync(hal->dev, 0); + if (i2s_config->communication_format & I2S_COMM_FORMAT_PCM_SHORT) { + if (i2s_config->mode & I2S_MODE_TX) { + i2s_ll_set_tx_short_sync(hal->dev, 1); + } + if (i2s_config->mode & I2S_MODE_RX) { + i2s_ll_set_rx_short_sync(hal->dev, 1); + } + } + } +} + +void i2s_hal_enable_master_mode(i2s_hal_context_t *hal) +{ + i2s_ll_set_tx_slave_mod(hal->dev, 0); //MASTER Slave + i2s_ll_set_rx_slave_mod(hal->dev, 1); //RX Slave +} + +void i2s_hal_enable_slave_mode(i2s_hal_context_t *hal) +{ + i2s_ll_set_tx_slave_mod(hal->dev, 1); //TX Slave + i2s_ll_set_rx_slave_mod(hal->dev, 1); //RX Slave +} + +void i2s_hal_init(i2s_hal_context_t *hal, int i2s_num) +{ + //Get hardware instance. + hal->dev = I2S_LL_GET_HW(i2s_num); +} diff --git a/docs/Doxyfile b/docs/Doxyfile index 523c03c9d..e45d5c2e1 100644 --- a/docs/Doxyfile +++ b/docs/Doxyfile @@ -105,6 +105,7 @@ INPUT = \ ../../components/esp_adc_cal/include/esp_adc_cal.h \ ../../components/soc/include/hal/spi_types.h \ ../../components/soc/include/hal/pcnt_types.h \ + ../../components/soc/include/hal/i2s_types.h \ ../../components/soc/esp32/include/soc/adc_channel.h \ ../../components/soc/esp32/include/soc/dac_channel.h \ ../../components/soc/esp32/include/soc/touch_channel.h \