Преглед изворни кода

Update I2S driver for esp32s2beta.

kooho пре 6 година
родитељ
комит
2139ca668d

+ 3 - 3
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")

+ 71 - 85
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)) {

+ 10 - 2
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

+ 50 - 0
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,
+    }
+};

+ 18 - 0
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

+ 2 - 1
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

+ 36 - 0
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,
+    }
+};

+ 18 - 0
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

+ 1 - 1
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.

+ 15 - 14
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_ */

+ 2 - 1
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

+ 31 - 0
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

+ 3 - 3
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
 

+ 3 - 3
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)