I2S 24bit Slave

StijnVM
Posts: 4
Joined: Mon Jul 30, 2018 7:31 pm

I2S 24bit Slave

Postby StijnVM » Sun Aug 05, 2018 4:18 pm

Hello!

I already reported the problem I'm having in the ESP-IDF subforum but this may be a better place.
See https://esp32.com/viewtopic.php?f=13&t=6582 for more detail but in a nutshell:

Trying to interface the ESP32 with a USB to I2S bridge which can only be configured as an I2S master and instead of using a continuous clock, outputs bursts of 24 clockpulses for each sample. ESP32 should only output data right now.

So I'm trying to use the ESP32 I2S in 24 bit slave mode but was seeing strange shifting behaviour in the audio data and now I've reduced the setup to 2 ESP32's to check if the problem could be the bursty clock. However, I'm still seeing some odd behaviour.

The code I'm using on the slave device:

Code: Select all

#include <stdio.h>
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "driver/i2s.h"
#include "esp_system.h"
#include <math.h>

#define I2S_NUM         (0)

static void setup_testblock()
{
   unsigned int n_blocks = 40;
    int *samples_data = malloc(8*n_blocks);
       size_t i2s_bytes_write = 0;

    unsigned int i;
    for(i = 0; i < n_blocks; i++)
    {
            samples_data[i*2] = -1431655681;          //0b101010101010101010101010(11111111) last byte should be dropped
            samples_data[i*2 + 1] = -286331137;         //0b111011101110111011101110(11111111) last byte should be dropped
    }

    i2s_write(I2S_NUM, samples_data, n_blocks*4, &i2s_bytes_write, 100);
    //i2s_write_expand(I2S_NUM, samples_data, ((bits+8)/16)*SAMPLE_PER_CYCLE*4, 16, 16, &i2s_bytes_write, 10);

    free(samples_data);
}
void app_main()
{
    i2s_config_t i2s_config = {
        .mode = I2S_MODE_SLAVE | I2S_MODE_TX,                                  // Only TX
        .sample_rate = 48000,
        .bits_per_sample = 24,
        .channel_format = I2S_CHANNEL_FMT_RIGHT_LEFT,                           //2-channels
        .communication_format = I2S_COMM_FORMAT_I2S | I2S_COMM_FORMAT_I2S_MSB,
        .dma_buf_count = 2,
        .dma_buf_len = 30,
        .use_apll = true,
        .intr_alloc_flags = ESP_INTR_FLAG_LEVEL1                               //Interrupt level 1
    };
    i2s_pin_config_t pin_config = {
        .bck_io_num = 26,
        .ws_io_num = 22,
        .data_out_num = 25,
        .data_in_num = -1                                                       //Not used
    };
    i2s_driver_install(0, &i2s_config, 0, NULL);
    i2s_set_pin(0, &pin_config);

    setup_testblock();
    while (1)
    {
        vTaskDelay(5000/portTICK_RATE_MS);
    }

}
If I understand correctly, it basically always writes the same pattern for left and right to the DMA buffers. The I2S peripheral then loops this data as output.
This works fine if I set both the master and slave to 32 bit. 0b10101010101010101010101011111111 and 0b11101110111011101110111011111111 is repeated. However, when I set the ESP's to 24 bit, the slave should drop the final byte (all the 1's). This happens most of the time.. but quite often, 2 bytes of zeroes are inserted, the data is shifted but then recovers on the falling LRClock.
See https://drive.google.com/file/d/1l0-Akl ... gBeJC/view and https://drive.google.com/file/d/1UeaQfL ... my2rn/view for scope screenshots.
Top is LRclock and bottom is Data.
I believe this problem is related to the problem I'm having with the USB-I2S bridge.

Since the testprogram is just sitting in the while(1) loop, I think the problem lies deeper than the software and may not be easy to solve..
Can anyone please confirm this behaviour? Any suggestions?

Thanks!

Who is online

Users browsing this forum: No registered users and 1 guest