From 765bf674d0d54b2b871bb2d1e41160bc4025da1a Mon Sep 17 00:00:00 2001 From: Mahavir Jain Date: Mon, 14 May 2018 14:33:45 +0530 Subject: [PATCH 1/2] i2s: add (optional) support to clear tx descriptor in underflow case It has been observed that, in case of underflow (data unavailability) in I2S transmission, previously filled up tx descriptors continue to get transmitted on line, causing noise in case of audio use case. This change adds optional `tx_desc_auto_clear` field during I2S driver intialization than can zero initialize tx descriptor in case of underflow situation in interrupt handler itself. Closes: https://github.com/espressif/esp-idf/issues/1789 --- components/driver/i2s.c | 8 ++++++++ components/driver/include/driver/i2s.h | 1 + 2 files changed, 9 insertions(+) diff --git a/components/driver/i2s.c b/components/driver/i2s.c index 65b83c9e7..480cd98ef 100644 --- a/components/driver/i2s.c +++ b/components/driver/i2s.c @@ -86,6 +86,7 @@ typedef struct { i2s_mode_t mode; /*!< I2S Working mode*/ uint32_t sample_rate; /*!< I2S sample rate */ bool use_apll; /*!< I2S use APLL clock */ + bool tx_desc_auto_clear; /*!< I2S auto clear tx descriptor on underflow */ int fixed_mclk; /*!< I2S fixed MLCK clock */ } i2s_obj_t; @@ -502,6 +503,12 @@ static void IRAM_ATTR i2s_intr_handler_default(void *arg) // 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); + // See if tx descriptor needs to be auto cleared: + // This will avoid any kind of noise that may get introduced due to transmission + // of previous data from tx descriptor on I2S line. + if (p_i2s->tx_desc_auto_clear == true) { + memset((void *) dummy, 0, p_i2s->tx->buf_size); + } } xQueueSendFromISR(p_i2s->tx->queue, (void*)(&finish_desc->buf), &high_priority_task_awoken); if (p_i2s->i2s_queue) { @@ -991,6 +998,7 @@ static esp_err_t i2s_param_config(i2s_port_t i2s_num, const i2s_config_t *i2s_co } p_i2s_obj[i2s_num]->use_apll = i2s_config->use_apll; + p_i2s_obj[i2s_num]->tx_desc_auto_clear = i2s_config->tx_desc_auto_clear; p_i2s_obj[i2s_num]->fixed_mclk = i2s_config->fixed_mclk; return ESP_OK; } diff --git a/components/driver/include/driver/i2s.h b/components/driver/include/driver/i2s.h index 1cd454796..1f73e1f55 100644 --- a/components/driver/include/driver/i2s.h +++ b/components/driver/include/driver/i2s.h @@ -139,6 +139,7 @@ typedef struct { 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; From 1751607adfe7078f89a2bd07ea7f0a261cf8421c Mon Sep 17 00:00:00 2001 From: Mahavir Jain Date: Fri, 23 Nov 2018 14:39:04 +0530 Subject: [PATCH 2/2] examples: enable option to auto clear I2S tx descriptor on underflow Closes: https://github.com/espressif/esp-idf/issues/1945 --- examples/bluetooth/a2dp_gatts_coex/main/main.c | 5 +++-- examples/bluetooth/a2dp_sink/main/main.c | 5 +++-- 2 files changed, 6 insertions(+), 4 deletions(-) diff --git a/examples/bluetooth/a2dp_gatts_coex/main/main.c b/examples/bluetooth/a2dp_gatts_coex/main/main.c index cf5117045..3b042714a 100644 --- a/examples/bluetooth/a2dp_gatts_coex/main/main.c +++ b/examples/bluetooth/a2dp_gatts_coex/main/main.c @@ -650,8 +650,9 @@ void app_main() .channel_format = I2S_CHANNEL_FMT_RIGHT_LEFT, //2-channels .communication_format = I2S_COMM_FORMAT_I2S | I2S_COMM_FORMAT_I2S_MSB, .dma_buf_count = 6, - .dma_buf_len = 60, // - .intr_alloc_flags = ESP_INTR_FLAG_LEVEL1 //Interrupt level 1 + .dma_buf_len = 60, + .intr_alloc_flags = 0, //Default interrupt priority + .tx_desc_auto_clear = true //Auto clear tx descriptor on underflow }; diff --git a/examples/bluetooth/a2dp_sink/main/main.c b/examples/bluetooth/a2dp_sink/main/main.c index 66850d30d..830afe45e 100644 --- a/examples/bluetooth/a2dp_sink/main/main.c +++ b/examples/bluetooth/a2dp_sink/main/main.c @@ -63,8 +63,9 @@ void app_main() .channel_format = I2S_CHANNEL_FMT_RIGHT_LEFT, //2-channels .communication_format = I2S_COMM_FORMAT_I2S_MSB, .dma_buf_count = 6, - .dma_buf_len = 60, // - .intr_alloc_flags = ESP_INTR_FLAG_LEVEL1 //Interrupt level 1 + .dma_buf_len = 60, + .intr_alloc_flags = 0, //Default interrupt priority + .tx_desc_auto_clear = true //Auto clear tx descriptor on underflow };