Page 1 of 1

Can one esp32 send audio data to another esp32 via I2s? Help appreciated

Posted: Wed May 06, 2020 8:52 pm
by mooalot
I am trying to get one esp32 to send its audio data to another esp32 via i2s. I am having a lot of trouble though.

The idea behind it is to create a task to read the data from the pins using i2s_num_1 and output the data onto a speaker using i2s_num_0 and an external i2s decoder. I know everything works except for what I provided in the code below.

The problem is that I am not quite sure how much data to receive when using i2s_read()

Here is my main:

Code: Select all

i2s_config_t i2s_config_in = {
        .mode = I2S_MODE_MASTER | I2S_MODE_RX,                                 
        .sample_rate = 44100,
        .bits_per_sample = 16,
        .channel_format = I2S_CHANNEL_FMT_RIGHT_LEFT,                           //2-channels
        .communication_format = I2S_COMM_FORMAT_PCM,
        .dma_buf_count = 6,
        .dma_buf_len = 60,
        .intr_alloc_flags = 0                                                 //Default interrupt priority
    };
    i2s_driver_install(1, &i2s_config_in, 0, NULL);

    i2s_pin_config_t pin_config_in = {
        .bck_io_num = 13,
        .ws_io_num = 15,
        .data_out_num = -1,
        .data_in_num = 21                                                      //Not used
    };

    i2s_set_pin(1, &pin_config_in);

    i2s_config_t i2s_config_out = {
        .mode = I2S_MODE_MASTER | I2S_MODE_TX,                                  // Only TX
        .sample_rate = 44100,
        .bits_per_sample = 16,
        .channel_format = I2S_CHANNEL_FMT_RIGHT_LEFT,                           //2-channels
        .communication_format = I2S_COMM_FORMAT_PCM,
        .dma_buf_count = 6,
        .dma_buf_len = 60,
        .intr_alloc_flags = 0,                                                  //Default interrupt priority
        .tx_desc_auto_clear = true                                              //Auto clear tx descriptor on underflow
    };
    i2s_driver_install(0, &i2s_config_out, 0, NULL);

    i2s_pin_config_t pin_config_out = {
        .bck_io_num = 26,
        .ws_io_num = 22,
        .data_out_num = 25,
        .data_in_num = -1                                                      //Not used
    };

    i2s_set_pin(0, &pin_config_out);


    ESP_LOGI(BT_APP_CORE_TAG, "It set the config");
    i2s_start_up();
And here is the i2s_start_up() code:

Code: Select all

static void bt_i2s_task_handler(void *arg)
{
    uint8_t *data = NULL;
    size_t item_size = 1;  //(I have no idea how to get the item size from the other esp32)
    size_t bytes_written = 0;
    size_t bytes_read = 0;

    for (;;) {
        i2s_read(1, data, item_size, &bytes_read, portMAX_DELAY);
        i2s_write(0, data, bytes_read, &bytes_written, portMAX_DELAY);
    }
}


void i2s_start_up(void) {
    xTaskCreate(bt_i2s_task_handler, "BtI2ST", 2048, NULL, configMAX_PRIORITIES - 3, &s_bt_i2s_task_handle);
    return;
}

When I run the code i get the following error:
Guru Meditation Error: Core 1 panic'ed (StoreProhibited). Exception was unhandled.
Core 1 register dump:
PC : 0x4000c333 PS : 0x00060030 A0 : 0x800d6924 A1 : 0x3ffc1470
A2 : 0x00000000 A3 : 0x3ffbd470 A4 : 0x00000001 A5 : 0x00000000
A6 : 0x00000000 A7 : 0x00000000 A8 : 0x00000000 A9 : 0x3ffc1420
A10 : 0x3ffc0054 A11 : 0x3ffbd258 A12 : 0x3ffbfe50 A13 : 0x00000001
A14 : 0x00000003 A15 : 0x00060023 SAR : 0x00000000 EXCCAUSE: 0x0000001d
EXCVADDR: 0x00000000 LBEG : 0x4000c2e0 LEND : 0x4000c2f6 LCOUNT : 0xffffffff

ELF file SHA256: a72a99211524cdeb932b273ad1e332af135051e67ec5493adb42e2294ca8a515

Backtrace: 0x4000c330:0x3ffc1470 0x400d6921:0x3ffc1480 0x400d4115:0x3ffc14b0 0x40087a3d:0x3ffc14e0
0x400d6921: i2s_read at /Users/gabe/esp/esp-idf/components/driver/i2s.c:1144

0x400d4115: bt_i2s_task_handler at /Users/gabe/development/basspack/a2dp_source/build/../main/bt_app_core.c:126 (discriminator 1)

0x40087a3d: vPortTaskWrapper at /Users/gabe/esp/esp-idf/components/freertos/port.c:143


Rebooting...

I am sure there are probably many problems with this code, but I am uncertain where to even begin. Any help would be great! Thanks!

Re: Can one esp32 send audio data to another esp32 via I2s? Help appreciated

Posted: Thu May 07, 2020 10:28 am
by ESP_Sprite
i2s_read does not allocate memory by itself, you need to make `data` a valid pointer to some memory. (Also, on your command wrt item_size: you can't know as I2S is a stream protocol.)

Re: Can one esp32 send audio data to another esp32 via I2s? Help appreciated

Posted: Thu May 07, 2020 4:40 pm
by mooalot
Okay, so I allocated some memory to the data and that seemed to fix many of the bugs! Thank you!

If I cannot know the size of the data, that probably means i2s_read() is not an option for this. Is there another efficient way to transfer the audio data from one esp32 to the other via pins?

Thanks!

Re: Can one esp32 send audio data to another esp32 via I2s? Help appreciated

Posted: Fri May 08, 2020 9:24 am
by ESP_Sprite
You could either use e.g. SPI or UART, or invent some kind of packetized format to send over I2S. However, do you actually *need* to know the size of what the other ESP sends? Can't you just keep streaming from I2S to the speaker?

Re: Can one esp32 send audio data to another esp32 via I2s? Help appreciated

Posted: Sat May 09, 2020 11:59 pm
by mooalot
I am just trying to see if I can understand I2s better by sending the data from one esp32 to another.

There is one thing I am confused about. The function

Code: Select all

i2s_read(i2s_port_t i2s_num, void *dest, size_t size, size_t *bytes_read, TickType_t ticks_to_wait)
is confusing. What does the term "size_t size" mean? The documentation says "Size of data in bytes", but what does that mean exactly? Is that the size of the data I am reading through I2s or is it the size of the space that I have allocated for the data?

Thanks!