pschatzmann / arduino-audio-tools

Arduino Audio Tools (a powerful Audio library not only for Arduino)
GNU General Public License v3.0
1.55k stars 237 forks source link

I2SStream Config RX Receive Data Pin #1591

Closed gameoverhack closed 5 months ago

gameoverhack commented 5 months ago

Problem Description

Firstly, thank you for such a great audio library!!

When using an I2S INMP441 Microphone I ran across a bug in the config settings necessary to set the RX receive pin. All examples I could find use the following kind of setup for using (custom) pins:

auto config = i2sStream.defaultConfig(RX_MODE);
config.port_no = I2S_NUM_0;
config.i2s_format = I2S_STD_FORMAT;//I2S_LSB_FORMAT;//I2S_PHILIPS_FORMAT;//I2S_MSB_FORMAT;
config.pin_bck = GPIO_NUM_32;
config.pin_data = GPIO_NUM_33;

// config.pin_data_rx = I2S_GPIO_UNUSED; // crashes when pin_data_rx is undefined

config.pin_ws = GPIO_NUM_25;
config.pin_mck = 0;
config.channels = channels;
config.sample_rate = sample_rate;
config.bits_per_sample = bit_rate;
config.buffer_count = 8; // default to power of 2 (not 6)
config.buffer_size = 64; // use more buffers instead of large buffer default
i2sStream.begin(config);

But on my Wemos D1 Mini ESP32 this leads to an exception fault:

11:26:30.286 -> Rebooting...
11:26:30.318 -> ets Jul 29 2019 12:21:46
11:26:30.319 -> 
11:26:30.319 -> rst:0xc (SW_CPU_RESET),boot:0x13 (SPI_FAST_FLASH_BOOT)
11:26:30.319 -> configsip: 0, SPIWP:0xee
11:26:30.319 -> clk_drv:0x00,q_drv:0x00,d_drv:0x00,cs0_drv:0x00,hd_drv:0x00,wp_drv:0x00
11:26:30.319 -> mode:DIO, clock div:1
11:26:30.319 -> load:0x3fff0030,len:1288
11:26:30.319 -> load:0x40078000,len:13872
11:26:30.319 -> load:0x40080400,len:4
11:26:30.319 -> ho 8 tail 4 room 4
11:26:30.319 -> load:0x40080404,len:3048
11:26:30.319 -> entry 0x40080590

Using ESP Detection Fault Decoder the stack trace is:

EXCVADDR: 0xd5d73210

Decoding stack results
0x400e5057: i2s_gpio_check_and_set at /home/runner/work/esp32-arduino-lib-builder/esp32-arduino-lib-builder/esp-idf/components/driver/i2s/i2s_common.c:722
0x400e5cc2: i2s_std_set_gpio at /home/runner/work/esp32-arduino-lib-builder/esp32-arduino-lib-builder/esp-idf/components/driver/i2s/i2s_std.c:151
0x400e6017: i2s_channel_init_std_mode at /home/runner/work/esp32-arduino-lib-builder/esp32-arduino-lib-builder/esp-idf/components/driver/i2s/i2s_std.c:211
0x400d4368:  is in audio_tools::I2SDriverESP32V1::DriverI2S::startChannels(audio_tools::I2SConfigESP32V1&, i2s_channel_obj_t*&, i2s_channel_obj_t*&, int, int) (/Users/gameoverair/Documents/Arduino/libraries/arduino-audio-tools/src/AudioI2S/I2SESP32V1.h:233).
0x400d4892:  is in audio_tools::I2SDriverESP32V1::begin(audio_tools::I2SConfigESP32V1, int, int) (/Users/gameoverair/Documents/Arduino/libraries/arduino-audio-tools/src/AudioI2S/I2SESP32V1.h:402).
0x400d498d: audio_tools::I2SDriverESP32V1::begin(audio_tools::I2SConfigESP32V1) at /Users/gameoverair/Documents/Arduino/libraries/arduino-audio-tools/src/AudioI2S/I2SESP32V1.h:71
0x400d5c0e: setup() at /Users/gameoverair/Documents/Arduino/libraries/arduino-audio-tools/src/AudioI2S/I2SStream.h:75
0x400e1f17: loopTask(void*) at /Users/gameoverair/Library/Arduino15/packages/esp32/hardware/esp32/3.0.1/cores/esp32/main.cpp:58`

As far as I can tell the issue is that pin_data_rx is undefined in I2SConfigESP32V1.h instead of equaling I2S_GPIO_UNUSED,(ie., -1), which leads to the following logic in I2SESP32V1.h at lines 67-69 evaluating pin_data_rx as an undefined int (eg., something like -283746823) and using it instead of pin_data :

        return begin(cfg, I2S_GPIO_UNUSED,
                     cfg.pin_data_rx != I2S_GPIO_UNUSED ? cfg.pin_data_rx
                                                        : cfg.pin_data);

Client side fix is to add the following to your config setup:

config.pin_data_rx = I2S_GPIO_UNUSED;

API side fix could be to give a default value to pin_data_rx of I2S_GPIO_UNUSED ie., in I2SConfigESP32V1.h add #include "driver/i2s_std.h"and change line 54 to:

int pin_data_rx = I2S_GPIO_UNUSED ;

I'm not testing other modes, but it occurs to me that rather than determining the RXTX mode solely from a pin define ternery operator, a more robust distinction could be given to the difference between RX and RXTX modes themselves, and then subsequent assignment of the pins?

Device Description

Wemos D1 Mini ESP32

Sketch

auto config = i2sStream.defaultConfig(RX_MODE);
config.port_no = I2S_NUM_0;
config.i2s_format = I2S_STD_FORMAT;//I2S_LSB_FORMAT;//I2S_PHILIPS_FORMAT;//I2S_MSB_FORMAT;
config.pin_bck = GPIO_NUM_32;
config.pin_data = GPIO_NUM_33;

// config.pin_data_rx = I2S_GPIO_UNUSED; // crashes when pin_data_rx is undefined

config.pin_ws = GPIO_NUM_25;
config.pin_mck = 0;
config.channels = channels;
config.sample_rate = sample_rate;
config.bits_per_sample = bit_rate;
config.buffer_count = 8; // default to power of 2 (not 6)
config.buffer_size = 64; // use more buffers instead of large buffer default
i2sStream.begin(config);

Other Steps to Reproduce

No response

What is your development environment

Arduino IDE and PlatformIO

I have checked existing issues, discussions and online documentation

pschatzmann commented 5 months ago

Thanks for your feed back: I have committed a correction that should make sure that no i2s pin is uninitialized.