Browse Source

Merge branch 'feature/i2s_tx_descriptor_auto_clear' into 'master'

i2s: add (optional) support to clear tx descriptor in underflow case

See merge request idf/esp-idf!2397
Angus Gratton 7 years ago
parent
commit
81231fcc4b

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

+ 1 - 0
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;
 

+ 3 - 2
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
     };
 
 

+ 3 - 2
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
     };