diff --git a/components/driver/CMakeLists.txt b/components/driver/CMakeLists.txt index 8e2ab494b..32e42b55f 100644 --- a/components/driver/CMakeLists.txt +++ b/components/driver/CMakeLists.txt @@ -1,6 +1,7 @@ set(COMPONENT_SRCS "can.c" "gpio.c" "i2c.c" + "i2s.c" "ledc.c" "pcnt.c" "periph_ctrl.c" @@ -17,9 +18,8 @@ set(COMPONENT_SRCS "can.c" "uart.c") if(CONFIG_IDF_TARGET_ESP32) - # SDMMC and MCPWM are in ESP32 only, I2S not ported yet. - list(APPEND COMPONENT_SRCS "i2s.c" - "mcpwm.c" + # SDMMC and MCPWM are in ESP32 only. + list(APPEND COMPONENT_SRCS "mcpwm.c" "sdio_slave.c" "sdmmc_host.c" "sdmmc_transaction.c") diff --git a/components/driver/i2s.c b/components/driver/i2s.c index 6b80c4d1e..904f1ef15 100644 --- a/components/driver/i2s.c +++ b/components/driver/i2s.c @@ -1,4 +1,4 @@ -// Copyright 2015-2016 Espressif Systems (Shanghai) PTE LTD +// 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. @@ -18,7 +18,7 @@ #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" @@ -97,8 +97,13 @@ typedef struct { } 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}; +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 int _i2s_adc_unit = -1; static int _i2s_adc_channel = -1; @@ -182,18 +187,23 @@ esp_err_t i2s_enable_tx_intr(i2s_port_t i2s_num) static esp_err_t i2s_isr_register(i2s_port_t i2s_num, int intr_alloc_flags, void (*fn)(void*), void * arg, i2s_isr_handle_t *handle) { - return esp_intr_alloc(ETS_I2S0_INTR_SOURCE + i2s_num, intr_alloc_flags, fn, arg, handle); + 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) { 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; @@ -393,7 +403,13 @@ 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]; //destroy old rx dma if exist @@ -419,6 +435,7 @@ esp_err_t i2s_set_clk(i2s_port_t i2s_num, uint32_t rate, i2s_bits_per_sample_t b clkmInteger = clkmdiv; clkmDecimals = (clkmdiv - clkmInteger) / denom; bck = mclk / b_clk; +#if SOC_I2S_SUPPORT_PDM } 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) { @@ -436,6 +453,7 @@ esp_err_t i2s_set_clk(i2s_port_t i2s_num, uint32_t rate, i2s_bits_per_sample_t b clkmInteger = clkmdiv; clkmDecimals = (clkmdiv - clkmInteger) / denom; bck = mclk / b_clk; +#endif } else { clkmInteger = clkmdiv; clkmDecimals = (clkmdiv - clkmInteger) / denom; @@ -455,18 +473,18 @@ esp_err_t i2s_set_clk(i2s_port_t i2s_num, uint32_t rate, i2s_bits_per_sample_t b 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; -#if CONFIG_IDF_TARGET_ESP32 +#ifdef CONFIG_IDF_TARGET_ESP32 I2S[i2s_num]->clkm_conf.clka_en = 1; -#elif CONFIG_IDF_TARGET_ESP32S2BETA +#elif defined CONFIG_IDF_TARGET_ESP32S2BETA I2S[i2s_num]->clkm_conf.clk_sel = 1; #endif double fi2s_rate = i2s_apll_get_fi2s(bits, sdm0, sdm1, sdm2, odir); 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 { -#if CONFIG_IDF_TARGET_ESP32 +#ifdef CONFIG_IDF_TARGET_ESP32 I2S[i2s_num]->clkm_conf.clka_en = 0; -#elif CONFIG_IDF_TARGET_ESP32S2BETA +#elif defined CONFIG_IDF_TARGET_ESP32S2BETA I2S[i2s_num]->clkm_conf.clk_sel = 2; #endif I2S[i2s_num]->clkm_conf.clkm_div_a = 63; @@ -498,6 +516,13 @@ 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) { + //Avoid spurious interrupt + return; + } + i2s_event_t i2s_event; int dummy; @@ -505,8 +530,8 @@ static void IRAM_ATTR i2s_intr_handler_default(void *arg) lldesc_t *finish_desc; - if (i2s_reg->int_st.out_dscr_err || i2s_reg->int_st.in_dscr_err) { - ESP_EARLY_LOGE(I2S_TAG, "dma error, interrupt status: 0x%08x", i2s_reg->int_st.val); + 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 (p_i2s->i2s_queue) { i2s_event.type = I2S_EVENT_DMA_ERROR; if (xQueueIsQueueFullFromISR(p_i2s->i2s_queue)) { @@ -516,7 +541,7 @@ static void IRAM_ATTR i2s_intr_handler_default(void *arg) } } - if (i2s_reg->int_st.out_eof && p_i2s->tx) { + if (int_st_val.out_eof && p_i2s->tx) { finish_desc = (lldesc_t*) i2s_reg->out_eof_des_addr; // All buffers are empty. This means we have an underflow on our hands. if (xQueueIsQueueFullFromISR(p_i2s->tx->queue)) { @@ -538,7 +563,7 @@ static void IRAM_ATTR i2s_intr_handler_default(void *arg) } } - if (i2s_reg->int_st.in_suc_eof && p_i2s->rx) { + if (int_st_val.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; if (xQueueIsQueueFullFromISR(p_i2s->rx->queue)) { @@ -553,11 +578,11 @@ 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; + if (high_priority_task_awoken == pdTRUE) { portYIELD_FROM_ISR(); } - - i2s_reg->int_clr.val = I2S[i2s_num]->int_st.val; } static esp_err_t i2s_destroy_dma_queue(i2s_port_t i2s_num, i2s_dma_t *dma) @@ -775,72 +800,37 @@ esp_err_t i2s_set_pin(i2s_port_t i2s_num, const i2s_pin_config_t *pin) //For TX unit, the input signal index should be I2SnO_xxx_IN_IDX if (p_i2s_obj[i2s_num]->mode & I2S_MODE_TX) { if (p_i2s_obj[i2s_num]->mode & I2S_MODE_MASTER) { - if (i2s_num == I2S_NUM_0) { - bck_sig = I2S0O_BCK_OUT_IDX; - ws_sig = I2S0O_WS_OUT_IDX; - data_out_sig = I2S0O_DATA_OUT23_IDX; - } else { - bck_sig = I2S1O_BCK_OUT_IDX; - ws_sig = I2S1O_WS_OUT_IDX; - data_out_sig = I2S1O_DATA_OUT23_IDX; - } + bck_sig = i2s_periph_signal[i2s_num].o_bck_out_sig; + ws_sig = i2s_periph_signal[i2s_num].o_ws_out_sig; + data_out_sig = i2s_periph_signal[i2s_num].o_data_out_sig; } else if (p_i2s_obj[i2s_num]->mode & I2S_MODE_SLAVE) { - if (i2s_num == I2S_NUM_0) { - bck_sig = I2S0O_BCK_IN_IDX; - ws_sig = I2S0O_WS_IN_IDX; - data_out_sig = I2S0O_DATA_OUT23_IDX; - } else { - bck_sig = I2S1O_BCK_IN_IDX; - ws_sig = I2S1O_WS_IN_IDX; - data_out_sig = I2S1O_DATA_OUT23_IDX; - } + bck_sig = i2s_periph_signal[i2s_num].o_bck_in_sig; + ws_sig = i2s_periph_signal[i2s_num].o_ws_in_sig; + data_out_sig = i2s_periph_signal[i2s_num].o_data_out_sig; } } //For RX unit, the output signal index should be I2SnI_xxx_OUT_IDX //For RX unit, the input signal index shuld be I2SnI_xxx_IN_IDX if (p_i2s_obj[i2s_num]->mode & I2S_MODE_RX) { if (p_i2s_obj[i2s_num]->mode & I2S_MODE_MASTER) { - if (i2s_num == I2S_NUM_0) { - bck_sig = I2S0I_BCK_OUT_IDX; - ws_sig = I2S0I_WS_OUT_IDX; - data_in_sig = I2S0I_DATA_IN15_IDX; - } else { - bck_sig = I2S1I_BCK_OUT_IDX; - ws_sig = I2S1I_WS_OUT_IDX; - data_in_sig = I2S1I_DATA_IN15_IDX; - } + bck_sig = i2s_periph_signal[i2s_num].i_bck_out_sig; + ws_sig = i2s_periph_signal[i2s_num].i_ws_out_sig; + data_in_sig = i2s_periph_signal[i2s_num].i_data_in_sig; } else if (p_i2s_obj[i2s_num]->mode & I2S_MODE_SLAVE) { - if (i2s_num == I2S_NUM_0) { - bck_sig = I2S0I_BCK_IN_IDX; - ws_sig = I2S0I_WS_IN_IDX; - data_in_sig = I2S0I_DATA_IN15_IDX; - } else { - bck_sig = I2S1I_BCK_IN_IDX; - ws_sig = I2S1I_WS_IN_IDX; - data_in_sig = I2S1I_DATA_IN15_IDX; - } + bck_sig = i2s_periph_signal[i2s_num].i_bck_in_sig; + ws_sig = i2s_periph_signal[i2s_num].i_ws_in_sig; + data_in_sig = i2s_periph_signal[i2s_num].i_data_in_sig; } } //For "full-duplex + slave" mode, we should select RX signal index for ws and bck. //For "full-duplex + master" mode, we should select TX signal index for ws and bck. if ((p_i2s_obj[i2s_num]->mode & I2S_FULL_DUPLEX_SLAVE_MODE_MASK) == I2S_FULL_DUPLEX_SLAVE_MODE_MASK) { - if (i2s_num == I2S_NUM_0) { - bck_sig = I2S0I_BCK_IN_IDX; - ws_sig = I2S0I_WS_IN_IDX; - } else { - bck_sig = I2S1I_BCK_IN_IDX; - ws_sig = I2S1I_WS_IN_IDX; - } + bck_sig = i2s_periph_signal[i2s_num].i_bck_in_sig; + ws_sig = i2s_periph_signal[i2s_num].i_ws_in_sig; } else if ((p_i2s_obj[i2s_num]->mode & I2S_FULL_DUPLEX_MASTER_MODE_MASK) == I2S_FULL_DUPLEX_MASTER_MODE_MASK) { - if (i2s_num == I2S_NUM_0) { - bck_sig = I2S0O_BCK_OUT_IDX; - ws_sig = I2S0O_WS_OUT_IDX; - } else { - bck_sig = I2S1O_BCK_OUT_IDX; - ws_sig = I2S1O_WS_OUT_IDX; - } + bck_sig = i2s_periph_signal[i2s_num].o_bck_out_sig; + ws_sig = i2s_periph_signal[i2s_num].o_ws_out_sig; } - gpio_matrix_out_check(pin->data_out_num, data_out_sig, 0, 0); gpio_matrix_in_check(pin->data_in_num, data_in_sig, 0); if (p_i2s_obj[i2s_num]->mode & I2S_MODE_MASTER) { @@ -862,12 +852,14 @@ esp_err_t i2s_set_sample_rates(i2s_port_t i2s_num, uint32_t rate) return i2s_set_clk(i2s_num, rate, p_i2s_obj[i2s_num]->bits_per_sample, p_i2s_obj[i2s_num]->channel_num); } +#if SOC_I2S_SUPPORT_PDM 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; 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 static esp_err_t i2s_param_config(i2s_port_t i2s_num, const i2s_config_t *i2s_config) { @@ -875,14 +867,11 @@ static esp_err_t i2s_param_config(i2s_port_t i2s_num, const i2s_config_t *i2s_co I2S_CHECK((i2s_config), "param null", ESP_ERR_INVALID_ARG); I2S_CHECK(!((i2s_config->mode & I2S_MODE_ADC_BUILT_IN) && (i2s_num != I2S_NUM_0)), "I2S ADC built-in only support on I2S0", ESP_ERR_INVALID_ARG); I2S_CHECK(!((i2s_config->mode & I2S_MODE_DAC_BUILT_IN) && (i2s_num != I2S_NUM_0)), "I2S DAC built-in only support on I2S0", ESP_ERR_INVALID_ARG); +#if SOC_I2S_SUPPORT_PDM I2S_CHECK(!((i2s_config->mode & I2S_MODE_PDM) && (i2s_num != I2S_NUM_0)), "I2S DAC PDM only support on I2S0", ESP_ERR_INVALID_ARG); - - if (i2s_num == I2S_NUM_1) { - periph_module_enable(PERIPH_I2S1_MODULE); - } else { - periph_module_enable(PERIPH_I2S0_MODULE); - } - +#endif + periph_module_enable(i2s_periph_signal[i2s_num].module); + if(i2s_config->mode & I2S_MODE_ADC_BUILT_IN) { //in ADC built-in mode, we need to call i2s_set_adc_mode to //initialize the specific ADC channel. @@ -963,6 +952,7 @@ static esp_err_t i2s_param_config(i2s_port_t i2s_num, const i2s_config_t *i2s_co 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; @@ -981,6 +971,10 @@ static esp_err_t i2s_param_config(i2s_port_t i2s_num, const i2s_config_t *i2s_co 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; @@ -1089,11 +1083,7 @@ 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. - if (i2s_num == I2S_NUM_1) { - periph_module_enable(PERIPH_I2S1_MODULE); - } else { - periph_module_enable(PERIPH_I2S0_MODULE); - } + 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); @@ -1166,12 +1156,8 @@ esp_err_t i2s_driver_uninstall(i2s_port_t i2s_num) free(p_i2s_obj[i2s_num]); p_i2s_obj[i2s_num] = NULL; + periph_module_disable(i2s_periph_signal[i2s_num].module); - if (i2s_num == I2S_NUM_0) { - periph_module_disable(PERIPH_I2S0_MODULE); - } else if (i2s_num == I2S_NUM_1) { - periph_module_disable(PERIPH_I2S1_MODULE); - } return ESP_OK; } @@ -1258,14 +1244,14 @@ esp_err_t i2s_write_expand(i2s_port_t i2s_num, const void *src, size_t size, siz I2S_CHECK((i2s_num < I2S_NUM_MAX), "i2s_num error", ESP_ERR_INVALID_ARG); I2S_CHECK((size > 0), "size must greater than zero", ESP_ERR_INVALID_ARG); I2S_CHECK((aim_bits * size < I2S_MAX_BUFFER_SIZE), "size is too large", ESP_ERR_INVALID_ARG); - I2S_CHECK((aim_bits >= src_bits), "aim_bits musn't less than src_bits", ESP_ERR_INVALID_ARG); + I2S_CHECK((aim_bits >= src_bits), "aim_bits mustn't be less than src_bits", ESP_ERR_INVALID_ARG); I2S_CHECK((p_i2s_obj[i2s_num]->tx), "tx NULL", ESP_ERR_INVALID_ARG); if (src_bits < I2S_BITS_PER_SAMPLE_8BIT || aim_bits < I2S_BITS_PER_SAMPLE_8BIT) { - ESP_LOGE(I2S_TAG,"bits musn't be less than 8, src_bits %d aim_bits %d", src_bits, aim_bits); + ESP_LOGE(I2S_TAG,"bits mustn't be less than 8, src_bits %d aim_bits %d", src_bits, aim_bits); return ESP_ERR_INVALID_ARG; } if (src_bits > I2S_BITS_PER_SAMPLE_32BIT || aim_bits > I2S_BITS_PER_SAMPLE_32BIT) { - ESP_LOGE(I2S_TAG,"bits musn't be greater than 32, src_bits %d aim_bits %d", src_bits, aim_bits); + ESP_LOGE(I2S_TAG,"bits mustn't be greater than 32, src_bits %d aim_bits %d", src_bits, aim_bits); return ESP_ERR_INVALID_ARG; } if ((src_bits == I2S_BITS_PER_SAMPLE_16BIT || src_bits == I2S_BITS_PER_SAMPLE_32BIT) && (size % 2 != 0)) { diff --git a/components/driver/include/driver/i2s.h b/components/driver/include/driver/i2s.h index 59c11978e..225cde85b 100644 --- a/components/driver/include/driver/i2s.h +++ b/components/driver/include/driver/i2s.h @@ -1,4 +1,4 @@ -// Copyright 2015-2016 Espressif Systems (Shanghai) PTE LTD +// 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. @@ -101,7 +101,9 @@ typedef enum { */ typedef enum { I2S_NUM_0 = 0x0, /*!< I2S 0*/ - I2S_NUM_1 = 0x1, /*!< I2S 1*/ +#if SOC_I2S_PERIPH_NUM > 1 + I2S_NUM_1, /*!< I2S 1*/ +#endif I2S_NUM_MAX, } i2s_port_t; @@ -118,7 +120,9 @@ typedef enum { 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; @@ -187,6 +191,7 @@ typedef struct { int data_in_num; /*!< DATA in pin*/ } i2s_pin_config_t; +#if SOC_I2S_SUPPORT_PDM /** * @brief I2S PDM RX downsample mode */ @@ -195,6 +200,7 @@ typedef enum { 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; /** @@ -221,6 +227,7 @@ typedef intr_handle_t i2s_isr_handle_t; */ esp_err_t i2s_set_pin(i2s_port_t i2s_num, const i2s_pin_config_t *pin); +#if SOC_I2S_SUPPORT_PDM /** * @brief Set PDM mode down-sample rate * In PDM RX mode, there would be 2 rounds of downsample process in hardware. @@ -239,6 +246,7 @@ esp_err_t i2s_set_pin(i2s_port_t i2s_num, const i2s_pin_config_t *pin); * - ESP_ERR_NO_MEM Out of memory */ esp_err_t i2s_set_pdm_rx_down_sample(i2s_port_t i2s_num, i2s_pdm_dsr_t dsr); +#endif /** * @brief Set I2S dac mode, I2S built-in DAC is disabled by default diff --git a/components/soc/esp32/i2s_periph.c b/components/soc/esp32/i2s_periph.c new file mode 100644 index 000000000..cd9fef98e --- /dev/null +++ b/components/soc/esp32/i2s_periph.c @@ -0,0 +1,50 @@ +// 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. + +#include "soc/i2s_periph.h" +#include "soc/gpio_sig_map.h" + +/* + 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] = { + { + .o_bck_in_sig = I2S0O_BCK_IN_IDX, + .o_ws_in_sig = I2S0O_WS_IN_IDX, + .o_bck_out_sig = I2S0O_BCK_OUT_IDX, + .o_ws_out_sig = I2S0O_WS_OUT_IDX, + .o_data_out_sig = I2S0O_DATA_OUT23_IDX, + .i_bck_in_sig = I2S0I_BCK_OUT_IDX, + .i_ws_in_sig = I2S0I_WS_OUT_IDX, + .i_bck_out_sig = I2S0I_BCK_IN_IDX, + .i_ws_out_sig = I2S0I_WS_IN_IDX, + .i_data_in_sig = I2S0I_DATA_IN15_IDX, + .irq = ETS_I2S0_INTR_SOURCE, + .module = PERIPH_I2S0_MODULE, + }, + { + .o_bck_in_sig = I2S1O_BCK_IN_IDX, + .o_ws_in_sig = I2S1O_WS_IN_IDX, + .o_bck_out_sig = I2S1O_BCK_OUT_IDX, + .o_ws_out_sig = I2S1O_WS_OUT_IDX, + .o_data_out_sig = I2S1O_DATA_OUT23_IDX, + .i_bck_in_sig = I2S1I_BCK_OUT_IDX, + .i_ws_in_sig = I2S1I_WS_OUT_IDX, + .i_bck_out_sig = I2S1I_BCK_IN_IDX, + .i_ws_out_sig = I2S1I_WS_IN_IDX, + .i_data_in_sig = I2S1I_DATA_IN15_IDX, + .irq = ETS_I2S1_INTR_SOURCE, + .module = PERIPH_I2S1_MODULE, + } +}; diff --git a/components/soc/esp32/include/soc/i2s_caps.h b/components/soc/esp32/include/soc/i2s_caps.h new file mode 100644 index 000000000..bddde5c61 --- /dev/null +++ b/components/soc/esp32/include/soc/i2s_caps.h @@ -0,0 +1,18 @@ +// 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 + +#define SOC_I2S_PERIPH_NUM (2) //ESP32 have 2 I2S +#define SOC_I2S_SUPPORT_PDM (1) //ESP32 support PDM diff --git a/components/soc/esp32/sources.cmake b/components/soc/esp32/sources.cmake index c6cb1965f..69765bb95 100644 --- a/components/soc/esp32/sources.cmake +++ b/components/soc/esp32/sources.cmake @@ -12,7 +12,8 @@ set(SOC_SRCS "cpu_util.c" "sdmmc_periph.c" "soc_memory_layout.c" "spi_periph.c" - "ledc_periph.c") + "ledc_periph.c" + "i2s_periph.c") if(NOT CMAKE_BUILD_EARLY_EXPANSION) set_source_files_properties("esp32/rtc_clk.c" PROPERTIES diff --git a/components/soc/esp32s2beta/i2s_periph.c b/components/soc/esp32s2beta/i2s_periph.c new file mode 100644 index 000000000..4e955ee06 --- /dev/null +++ b/components/soc/esp32s2beta/i2s_periph.c @@ -0,0 +1,36 @@ +// 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. + +#include "soc/i2s_periph.h" +#include "soc/gpio_sig_map.h" + +/* + 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] = { + { + .o_bck_in_sig = I2S0O_BCK_IN_IDX, + .o_ws_in_sig = I2S0O_WS_IN_IDX, + .o_bck_out_sig = I2S0O_BCK_OUT_IDX, + .o_ws_out_sig = I2S0O_WS_OUT_IDX, + .o_data_out_sig = I2S0O_DATA_OUT23_IDX, + .i_bck_in_sig = I2S0I_BCK_OUT_IDX, + .i_ws_in_sig = I2S0I_WS_OUT_IDX, + .i_bck_out_sig = I2S0I_BCK_IN_IDX, + .i_ws_out_sig = I2S0I_WS_IN_IDX, + .i_data_in_sig = I2S0I_DATA_IN15_IDX, + .irq = ETS_I2S0_INTR_SOURCE, + .module = PERIPH_I2S0_MODULE, + } +}; diff --git a/components/soc/esp32s2beta/include/soc/i2s_caps.h b/components/soc/esp32s2beta/include/soc/i2s_caps.h new file mode 100644 index 000000000..9dfa5bb6d --- /dev/null +++ b/components/soc/esp32s2beta/include/soc/i2s_caps.h @@ -0,0 +1,18 @@ +// 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 + +#define SOC_I2S_PERIPH_NUM (1) //ESP32-S2 have 1 I2S +#define SOC_I2S_SUPPORT_PDM (0) //ESP32-S2 do not support PDM diff --git a/components/soc/esp32s2beta/include/soc/i2s_reg.h b/components/soc/esp32s2beta/include/soc/i2s_reg.h index 219401a79..aa64b2ba1 100644 --- a/components/soc/esp32s2beta/include/soc/i2s_reg.h +++ b/components/soc/esp32s2beta/include/soc/i2s_reg.h @@ -1,4 +1,4 @@ -// Copyright 2017-2018 Espressif Systems (Shanghai) PTE LTD +// Copyright 2017-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. diff --git a/components/soc/esp32s2beta/include/soc/i2s_struct.h b/components/soc/esp32s2beta/include/soc/i2s_struct.h index c9a24e6b2..5be4b18d9 100644 --- a/components/soc/esp32s2beta/include/soc/i2s_struct.h +++ b/components/soc/esp32s2beta/include/soc/i2s_struct.h @@ -1,4 +1,4 @@ -// Copyright 2017-2018 Espressif Systems (Shanghai) PTE LTD +// Copyright 2017-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. @@ -408,18 +408,19 @@ typedef volatile struct { } pd_conf; union { struct { - uint32_t camera_en: 1; /*Set this bit to enable camera mode*/ - uint32_t lcd_tx_wrx2_en: 1; /*LCD WR double for one datum.*/ - uint32_t lcd_tx_sdx2_en: 1; /*Set this bit to duplicate data pairs (Frame Form 2) in LCD mode.*/ - uint32_t data_enable_test_en: 1; /*for debug camera mode enable*/ - uint32_t data_enable: 1; /*for debug camera mode enable*/ - uint32_t lcd_en: 1; /*Set this bit to enable LCD mode*/ - uint32_t ext_adc_start_en: 1; /*Set this bit to enable the function that ADC mode is triggered by external signal.*/ - uint32_t inter_valid_en: 1; /*Set this bit to enable camera internal valid*/ - uint32_t cam_sync_fifo_reset: 1; /*Set this bit to reset cam_sync_fifo*/ - uint32_t cam_clk_loopback: 1; /*Set this bit to loopback cam_clk from i2s_rx*/ - uint32_t cam_sync_fifo_reset_st: 1; - uint32_t reserved11: 21; + uint32_t camera_en: 1; /*Set this bit to enable camera mode*/ + uint32_t lcd_tx_wrx2_en: 1; /*LCD WR double for one datum.*/ + uint32_t lcd_tx_sdx2_en: 1; /*Set this bit to duplicate data pairs (Frame Form 2) in LCD mode.*/ + uint32_t data_enable_test_en: 1; /*for debug camera mode enable*/ + uint32_t data_enable: 1; /*for debug camera mode enable*/ + uint32_t lcd_en: 1; /*Set this bit to enable LCD mode*/ + uint32_t ext_adc_start_en: 1; /*Set this bit to enable the function that ADC mode is triggered by external signal.*/ + uint32_t inter_valid_en: 1; /*Set this bit to enable camera internal valid*/ + uint32_t cam_sync_fifo_reset: 1; /*Set this bit to reset cam_sync_fifo*/ + uint32_t cam_clk_loopback: 1; /*Set this bit to loopback cam_clk from i2s_rx*/ + uint32_t i_v_sync_filter_en: 1; + uint32_t i_v_sync_filter_thres: 3; + uint32_t reserved14: 18; }; uint32_t val; } conf2; @@ -502,4 +503,4 @@ extern i2s_dev_t I2S1; } #endif -#endif /* _SOC_I2S_STRUCT_H_ */ +#endif /* _SOC_I2S_STRUCT_H_ */ \ No newline at end of file diff --git a/components/soc/esp32s2beta/sources.cmake b/components/soc/esp32s2beta/sources.cmake index d4c8e9d52..8b8849b93 100644 --- a/components/soc/esp32s2beta/sources.cmake +++ b/components/soc/esp32s2beta/sources.cmake @@ -8,7 +8,8 @@ set(SOC_SRCS "cpu_util.c" "rtc_time.c" "soc_memory_layout.c" "spi_periph.c" - "ledc_periph.c") + "ledc_periph.c" + "i2s_periph.c") if(NOT CMAKE_BUILD_EARLY_EXPANSION) set_source_files_properties("esp32s2beta/rtc_clk.c" PROPERTIES diff --git a/components/soc/include/soc/i2s_periph.h b/components/soc/include/soc/i2s_periph.h index 7e4e2ed1a..0c6e003ad 100644 --- a/components/soc/include/soc/i2s_periph.h +++ b/components/soc/include/soc/i2s_periph.h @@ -13,5 +13,36 @@ // limitations under the License. #pragma once +#include "soc/soc.h" +#include "soc/periph_defs.h" #include "soc/i2s_struct.h" #include "soc/i2s_reg.h" +#include "soc/i2s_caps.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/* + Stores a bunch of per-I2S-peripheral data. +*/ +typedef struct { + const uint8_t o_bck_in_sig; + const uint8_t o_ws_in_sig; + const uint8_t o_bck_out_sig; + const uint8_t o_ws_out_sig; + const uint8_t o_data_out_sig; + const uint8_t i_bck_in_sig; + const uint8_t i_ws_in_sig; + const uint8_t i_bck_out_sig; + const uint8_t i_ws_out_sig; + const uint8_t i_data_in_sig; + const uint8_t irq; + const periph_module_t module; +} i2s_signal_conn_t; + +extern const i2s_signal_conn_t i2s_periph_signal[SOC_I2S_PERIPH_NUM]; + +#ifdef __cplusplus +} +#endif diff --git a/examples/peripherals/i2s/README.md b/examples/peripherals/i2s/README.md index 8f16374f1..b1632da12 100644 --- a/examples/peripherals/i2s/README.md +++ b/examples/peripherals/i2s/README.md @@ -53,9 +53,9 @@ If you have a logic analyzer, you can use a logic analyzer to grab online data. | pin name| function | gpio_num | |:---:|:---:|:---:| -| WS |word select| GPIO_NUM_25 | -| SCK |continuous serial clock| GPIO_NUM_26 | -| SD |serial data| GPIO_NUM_22 | +| WS |word select| GPIO_NUM_15 | +| SCK |continuous serial clock| GPIO_NUM_13 | +| SD |serial data| GPIO_NUM_21 | ## Troubleshooting diff --git a/examples/peripherals/i2s/main/i2s_example_main.c b/examples/peripherals/i2s/main/i2s_example_main.c index 36bbabc18..dde01e714 100644 --- a/examples/peripherals/i2s/main/i2s_example_main.c +++ b/examples/peripherals/i2s/main/i2s_example_main.c @@ -21,9 +21,9 @@ #define I2S_NUM (0) #define WAVE_FREQ_HZ (100) #define PI (3.14159265) -#define I2S_BCK_IO (GPIO_NUM_26) -#define I2S_WS_IO (GPIO_NUM_25) -#define I2S_DO_IO (GPIO_NUM_22) +#define I2S_BCK_IO (GPIO_NUM_13) +#define I2S_WS_IO (GPIO_NUM_15) +#define I2S_DO_IO (GPIO_NUM_21) #define I2S_DI_IO (-1) #define SAMPLE_PER_CYCLE (SAMPLE_RATE/WAVE_FREQ_HZ)