Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Changing I2S sample rate changes word-order of I2S output (IDFGH-3448) #5410

Closed
ikostoski opened this issue Jun 7, 2020 · 5 comments
Closed

Comments

@ikostoski
Copy link

ikostoski commented Jun 7, 2020

Environment

  • Development Kit: [ESP32-S2-Saola-1R]
  • Kit version (?): [ESP-ROM:esp32s2-rc4-20191025]
  • Module or chip used: [ESP32-S2]
  • IDF version: 4.2-dev-1660-g7d75213 (master)
  • Build System: [idf.py]
  • Compiler version: xtensa-esp32-elf-gcc (crosstool-NG esp-2020r1) 8.2.0
  • Operating System: [Windows]
  • (Windows only) environment type: [VS Code / ESP-IDF extension].
  • Using an IDE?: [Yes (VSCode)]
  • Power Supply: [USB]

Problem Description

After changing I2S sampling rate, word-order output on I2S pins changes

Expected Behavior

Changing sampling rate should not change I2S word-order output

Actual Behavior

After call to i2s_set_sample_rates, I2S output word order is changed and unpredictable

Steps to reproduce

  1. Run supplied code snippet and monitor output of I2S pins (i.e. with logic analyzer, etc...)

// If possible, attach a picture of your setup/wiring here.
Only logic analyzer is attached to pins 21(DO) and 26(WS)

Code to reproduce this issue

#include <stdio.h>
#include "driver/i2s.h"
#include "sdkconfig.h"

// Adjust these as needed, tested with IO21(DO) and IO26(WS)
#define I2S_WS_GPIO CONFIG_I2S_WS_GPIO
#define I2S_DO_GPIO CONFIG_I2S_DO_GPIO

void app_main(void) {

  printf("Setting up I2S0");
  i2s_config_t i2s_config = {
    .mode = I2S_MODE_MASTER | I2S_MODE_TX,
    .sample_rate = 44100L, 
    .bits_per_sample = I2S_BITS_PER_SAMPLE_16BIT, 
    .channel_format = I2S_CHANNEL_FMT_RIGHT_LEFT, 
    .communication_format = I2S_COMM_FORMAT_I2S | I2S_COMM_FORMAT_I2S_MSB,
    .intr_alloc_flags = ESP_INTR_FLAG_LEVEL1, 
    .dma_buf_count = 8,
    .dma_buf_len = 256, 
    .use_apll = true,
  };
  if (i2s_driver_install(0, &i2s_config, 0, NULL) != ESP_OK) {
    printf("ERROR: Unable to install I2S drivers\n");
    return;
  }

  i2s_pin_config_t pins = {
    .bck_io_num = I2S_PIN_NO_CHANGE,
    .ws_io_num = I2S_WS_GPIO ,
    .data_out_num = I2S_DO_GPIO ,
    .data_in_num = I2S_PIN_NO_CHANGE
  };
  if (i2s_set_pin(0, &pins) != ESP_OK) {
    printf("ERROR setting up I2S pins\n");
    i2s_driver_uninstall(0);
    return;
  }

  // Pattern we are sending
  // Expected output should be repeating series of positive pulses
  // [1, 2, 3, 4, 5, 6, 0, long_pulse]
  uint32_t buf[4] = {0x8000a000u, 0xa800aa00u, 0xaa80aaa0u, 0x0000fffeu};

  // Send the same data for approx 10sec (44.1KHz x 10sec)
  printf("Sending initial I2S data for ~10 seconds...\n");
  for(int i=0; i<110250L; i++) {
    uint32_t bytes_written;
    esp_err_t ret = i2s_write(0, (const char*)&buf, sizeof(buf), &bytes_written, portMAX_DELAY);
    if (ret != ESP_OK) {
      printf("ERROR %d writing to I2S", ret);
      break;
    }
  }

  // Change of the I2S sampling rate
  i2s_set_sample_rates(0, 48000);

  // Send the same data for approx 10sec (48KHz x 10sec)
  // However, the output as seen on the I2S pin, in the next 10 seconds looks like
  // [2, 0, 4, 1, 6, 3, long_pulse, 6]

  printf("Sending same I2S data, with changed sampling rate, for ~10 seconds...\n");
  for(int i=0; i<120000L; i++) {
    uint32_t bytes_written;
    esp_err_t ret = i2s_write(0, (const char*)&buf, sizeof(buf), &bytes_written, portMAX_DELAY);
    if (ret != ESP_OK) {
      printf("ERROR %d writing to I2S", ret);
      break;
    }
  }

  printf("Done\n");
  i2s_driver_uninstall(0);
}

Debug Logs

N/A. Problem is visible only on actual output of I2S pins

Other items if possible

N/A

@github-actions github-actions bot changed the title Changing I2S sample rate changes word-order of I2S output Changing I2S sample rate changes word-order of I2S output (IDFGH-3448) Jun 7, 2020
@Alvin1Zhang
Copy link
Collaborator

@ikostoski Thanks for the detailed report, we will look into.

@koobest
Copy link
Contributor

koobest commented Jun 8, 2020

Hi, @ikostoski
Because the I2S and DMA are not reset correctly. we will fix this issue soon. Can you help test it?

The fix is to change the following function:

// components/soc/src/hal/i2s_hal.c

void i2s_hal_reset(i2s_hal_context_t *hal)
{
    i2s_ll_reset_tx(hal->dev);
    i2s_ll_reset_rx(hal->dev);
    i2s_ll_reset_dma_in(hal->dev);
    i2s_ll_reset_dma_out(hal->dev);
    i2s_ll_reset_rx_fifo(hal->dev);
    i2s_ll_reset_tx_fifo(hal->dev);
}
// components/driver/i2s.c

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);
    i2s_hal_reset(&(p_i2s_obj[i2s_num]->hal));

    esp_intr_disable(p_i2s_obj[i2s_num]->i2s_isr_handle);
    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_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_hal_start_rx(&(p_i2s_obj[i2s_num]->hal));
    }
    esp_intr_enable(p_i2s_obj[i2s_num]->i2s_isr_handle);
    I2S_EXIT_CRITICAL();
    return ESP_OK;
}

thanks !!

@ikostoski
Copy link
Author

Hi @koobest,

It appears that with these changes, the problem is fixed. After changing the sample rate, the output is again in expected word-order.

Thank You!

@ikostoski
Copy link
Author

Hi @koobest,
Will the above fix eventually be merged? As far as I was able to test it, it works.
Thanks.

@koobest
Copy link
Contributor

koobest commented Jul 14, 2020

Hi, The fix has been merged into the internal repository and will be released soon.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants