24-bit I2S BCLK/LRCLK issue

palmerr23
Posts: 4
Joined: Mon Feb 22, 2021 3:59 am

24-bit I2S BCLK/LRCLK issue

Postby palmerr23 » Thu Jan 19, 2023 2:58 am

I'm having difficulty getting LRCLK and BCLK correct with 24-bit I2S.

With 48k sample rate I'm getting the correct MCLK (12.288) however LRCLK is around 51 kHz, BCLK is correctly aligned to LRCLK.
At 44.1KHz same issue with LRCLK close to 47kHz.

The issue occurs on both an S3 and a traditional ESP32 DevkitC.

Is there something I'm not setting correctly?
ESP32 I2S 24 bit issue.jpg
ESP32 I2S 24 bit issue.jpg (161.38 KiB) Viewed 947 times

Code: Select all

/****************************************************
 * SIMPLE I2S test 
TX mode - I2S0
Signed 24 bit data
48kHz
ESP32-S3 or ESP32
ESP32 2.0.6 - IDF 4.4
Arduino 1.8.19
 * *************************************************/
#define STATS // print stats 
#include <Arduino.h>
int samplerate = 48000;  
//int samplerate = 44100;  

#define BUFSIZE    128  // 32 bit samples
#define SAMPSIZE    4   // length of sample variable for ibuf/obuf
#define DMASAMPSIZE    3  // length of sample variable for ibuf/obuf
#define DMA_BUFS    4    
#define DMABUFSIZ   (BUFSIZE * DMASAMPSIZE) // bytes ( < 4096)

int32_t obuf[BUFSIZE];
int32_t ibuf[BUFSIZE];

#define LEFT 0
#define RIGHT 1

//#define S3
#ifdef S3
  #define DATA_IN 37  //S3 GPIO MUX allows any pin mappings
  #define MCLK 38    
  #define BCLK 39    
  #define LRCLK 40  
  #define DATA_OUT 41 
#else // std ES32 
  #define MCLK 0    // Earlier ESP32s support setting MCLK on GPIO0/GPIO1/GPIO3 only
  #define BCLK 5    
  #define LRCLK 25 
  #define DATA_IN 35
  #define DATA_OUT 27 
#endif

#define I2S_CORE 1
#include <driver/i2s.h>

#define STD_I2S
#ifdef STD_I2S // Phillips: +1 bit/frame
  //#define I2S_AFMT I2S_COMM_FORMAT_STAND_I2S 
  #define I2S_AFMT I2S_COMM_FORMAT_I2S
#else // MSB format, no pre-bit
 #define I2S_AFMT I2S_COMM_FORMAT_STAND_MSB  
  //#define I2S_AFMT I2S_COMM_FORMAT_I2S_MSB
#endif

i2s_port_t i2s_num_x = I2S_NUM_0; 
i2s_config_t i2s_config_x;

TaskHandle_t AudioStreamTaskHandle;
static void AudioStreamTask(void * pvParameters);

void setup() {
  Serial.begin(115200);
  delay(1000);
  Serial.println("\n\***** I2S - 24 bit test *****");

  //fillBuf_32();
  fillBuf_24();
  //fillBuf_16();
  printbuf();
  Serial.println("** Start I2S.");
  configure_i2s(samplerate); 
  Serial.printf("Real I2S rate %4.3f\n", i2s_get_clk(i2s_num_x));
 
  xTaskCreatePinnedToCore(AudioStreamTask, "AudioStreamTask", 20000, NULL, 4, &AudioStreamTaskHandle, I2S_CORE);
  Serial.println("Setup done");
}

void loop() 
{
  // processing occurs in pinned task AudioStreamTask()
  delay(5000);  
  yield();
}

static void AudioStreamTask(void * pvParameters){
  size_t  bytesOut, bytesIn;
  esp_err_t errchk;
  while(1)
  {
    // blocks until a DMA buffer is available
    errchk =  i2s_write(i2s_num_x, &obuf[0], DMABUFSIZ, &bytesOut, portMAX_DELAY );    
  
    if(bytesOut < 100 || errchk != ESP_OK)
      Serial.printf("Bad I2S write %i bytes, err %i\n", bytesOut, errchk);    
 
    vTaskDelay(1); 
  }
}
volatile bool i2s_running = false;
void configure_i2s(int SampleRate)
{
#ifdef STATS 
  Serial.printf("I2S out: sample rate %u\n", SampleRate);
#endif

  i2s_config_x = {
    .mode = (i2s_mode_t)(I2S_MODE_MASTER | I2S_MODE_TX ), //| I2S_MODE_RX
    .sample_rate = samplerate, 
    .bits_per_sample = I2S_BITS_PER_SAMPLE_24BIT,   
    .channel_format = I2S_CHANNEL_FMT_RIGHT_LEFT, 
    .communication_format = (i2s_comm_format_t)(I2S_AFMT),
    .intr_alloc_flags = ESP_INTR_FLAG_LEVEL1, 
    .dma_buf_count = DMA_BUFS,
    .dma_buf_len = DMABUFSIZ,
    .use_apll = 1, 
    .mclk_multiple = I2S_MCLK_MULTIPLE_256
  };
  
  static const i2s_pin_config_t pin_config_x = 
  {
    .mck_io_num   = MCLK,
    .bck_io_num   = BCLK, 
    .ws_io_num    = LRCLK,
    .data_out_num = DATA_OUT, 
    .data_in_num  = I2S_PIN_NO_CHANGE//DATA_IN 
  };

  if(i2s_running)
  {
    i2s_stop(i2s_num_x);
    i2s_driver_uninstall(i2s_num_x);
  }    
  i2s_driver_install(i2s_num_x, &i2s_config_x, 0, NULL);   //install and start i2s driver
  i2s_set_pin(i2s_num_x, &pin_config_x);
  i2s_set_sample_rates(i2s_num_x, SampleRate); //set sample rates
  i2s_zero_dma_buffer(i2s_num_x);
  i2s_running = true;
}

void fillBuf_32() // fill with a simple sequence, 32 bit offsets
{
  for (int i = 0; i < BUFSIZE; i++)
    obuf[i] = i;
}
void fillBuf_24() // fill with a simple sequence, 24 bit offsets
{
  char * sp = (char *)&obuf;
  //sp +=3; // start at the low byte
  int count = BUFSIZE * 32/24; 
  int i;
  for (i = 0; i < BUFSIZE; i++)
     obuf[i] = 0;
  for (i = 0; i < count; i++)
  {
    *sp = i+1;
     sp += 3;
  }
}
void fillBuf_16() // fill first BUFSIZE with a simple sequence, 16 bit offsets
{
  char * sp = (char *)&obuf;
  int count = BUFSIZE; 
  int i;
  for (i = 0; i < BUFSIZE; i++)
     obuf[i] = 0;
  for (i = 0; i < count; i++)
  {
    *sp = i+1;
     sp += 2;
  }
}
void printbuf()
{
  for (int i = 0; i < 10; i++)
  Serial.printf(" 0x%08x,", obuf[i]);
}
Attachments
ESP32 I2S 24 bit issue.jpg
ESP32 I2S 24 bit issue.jpg (161.38 KiB) Viewed 947 times

Who is online

Users browsing this forum: No registered users and 212 guests