Confused over i2s_config_t

blippy
Posts: 17
Joined: Tue Jun 25, 2019 7:36 am

Confused over i2s_config_t

Postby blippy » Sun Jun 30, 2019 12:37 pm

So, I have a big block of data that I want to write to I2S. The data consists of 8-bit mono audio, sample rate 8kHz. I want the output on the DAC (pin 25).

I figured that a way to do it is to write in blocks of 512 bytes using i2s_write(). However I am getting

Code: Select all

E (283) I2S: Invalid bits per sample
when calling:

Code: Select all

ret = i2s_driver_install(0, &i2s_config, 0, NULL);
So it looks like I have configured the driver wrong. Here's how I set i up:

Code: Select all

      static const i2s_config_t i2s_config = {
                .mode = I2S_MODE_MASTER | I2S_MODE_TX | I2S_MODE_DAC_BUILT_IN,
                //.mode = I2S_MODE_MASTER | I2S_MODE_TX | I2S_MODE_DAC_BUILT_IN,
                .sample_rate = 8000,
                .bits_per_sample = 8, 
                .channel_format = I2S_CHANNEL_FMT_ONLY_LEFT,
                .communication_format = I2S_COMM_FORMAT_I2S_MSB,
                .intr_alloc_flags = 0, // default interrupt priority
                .dma_buf_count = 4,
                .dma_buf_len = 512/4/8,
                .use_apll = false
                        //.intr_alloc_flags = ESP_INTR_FLAG_LEVEL1
        };
I'm confused as to how to set .dma_buf_count and .dma_buf_len. Presumably there's a relationship between sample_rate, bits_per_sample, dma_buf_count and dma_buf_len, but I am at loss as to know how to set it.

I'm assuming that dma_buf_count is a more-or-less arbitrary number, and that the dma_buf_len multiplied by dma_buf_count must equal some other number.

blippy
Posts: 17
Joined: Tue Jun 25, 2019 7:36 am

Re: Confused over i2s_config_t

Postby blippy » Sun Jun 30, 2019 4:57 pm

One thing occurred to me: is the reason that I can't set bits_per_sample to 8 because data has to be word-aligned, i.e. to even addresses?

blippy
Posts: 17
Joined: Tue Jun 25, 2019 7:36 am

Re: Confused over i2s_config_t

Postby blippy » Sun Jun 30, 2019 5:24 pm

OK, I've assumed that the data needs to be as 16-bit ints rather than 8-bit ints. I've therefore created a main section that loops over the track endlessly:

Code: Select all

void app_main()
{
        //int n=0;
        esp_err_t ret;


        static const int i2s_num = 0; // i2s port number

        static const i2s_config_t i2s_config = {
                .mode = I2S_MODE_MASTER | I2S_MODE_TX | I2S_MODE_DAC_BUILT_IN,
                //.mode = I2S_MODE_MASTER | I2S_MODE_TX | I2S_MODE_DAC_BUILT_IN,
                .sample_rate = 8000,
                .bits_per_sample = 16,
                .channel_format = I2S_CHANNEL_FMT_ONLY_LEFT,
                .communication_format = I2S_COMM_FORMAT_I2S_MSB,
                .intr_alloc_flags = 0, // default interrupt priority
                .dma_buf_count = 8,
                .dma_buf_len = 64,
                .use_apll = false
                        //.intr_alloc_flags = ESP_INTR_FLAG_LEVEL1
        };

        ret = i2s_driver_install(i2s_num, &i2s_config, 0, NULL);
        assert(ret == ESP_OK);
        ret = i2s_set_clk(0, 8000, 16, I2S_CHANNEL_MONO);
        assert(ret == ESP_OK);
        ret = i2s_set_dac_mode(I2S_DAC_CHANNEL_LEFT_EN);
        assert(ret == ESP_OK);


        size_t nbytes;
        while(1) {
                for(int i = 0 ; i < track_raw_len; ++i) {
                        uint16_t vol = track_raw[i] << 8;
                        ret = i2s_write(0, &vol , 2, &nbytes, portMAX_DELAY);
                        assert(ret == ESP_OK);
                }
                puts("Seems to have written OK");
        }

        for(;;) {
                vTaskDelay(1000 / portTICK_PERIOD_MS);
        }
}

It seems to work, but I'm not sure if it's terribly efficient. Is there a better way for doing this?

I'm really struggling to understand what's going on, but presumably the dma_buf_count and the dma_buf_len are some kind of buffer arrangement that creates better CPU utilisation, and that I am essentially undermining this by turning an 8-bit byte into a 16-bit word and sending only 2 bytes over to i2s.

Who is online

Users browsing this forum: ok-home and 125 guests