Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

using the I2S output as slave (connect to a ADAU1701 DSP) #218

Answered by pschatzmann
jmibk asked this question in Q&A
Discussion options

I try to use the arduino audio tools lib in connection with an ESP32 board to stream Bluetooth to I2S and then into an Audio DSP I2S input.

If I connect any DAC to the I2C output of the ESP, everything works great.

Now if I connect the ESP32 to the DSP, the DSP is the master device, so it delivers a clock itself. In that case I have to feed the ESP32 with the clock signals from the DSP. I think this must be called I2S output as slave on the ESP32.

I don't know, how to configure the I2S on the ESP to this slave mode, that the DSP gives the bit (or master) clock to the ESP?

Has anyone connected a ESP32 with the arduino audio tools lib to any external DSP that operates in master mode?

This is my setup code based on the Basic A2DP to I2S example.

`void setup() {
Serial.begin(115200);
AudioLogger::instance().begin(Serial, AudioLogger::Warning);

// register callback
a2dp_sink.set_stream_reader(read_data_stream, false);

// Start Bluetooth Audio Receiver
a2dp_sink.set_auto_reconnect(false);
a2dp_sink.start("a2dp-i2s");

// setup output
auto cfg = i2s.defaultConfig();
cfg.pin_data = 13;
cfg.pin_ws = 14;
cfg.pin_bck = 15;
cfg.sample_rate = a2dp_sink.sample_rate();
cfg.channels = 2;
cfg.bits_per_sample = 16;
//cfg.is_master = false; //is not working.
i2s.begin(cfg);
}`

You must be logged in to vote

if cfg.is_master = false; then the ESP32 expects that the values for pin_bck and pin_ws are provided by the external system.
If this is not working I would suggest to look for the issue on the Audio DSP side.

I have never tried but I doubt that this is also working for the pin_mck.

In any case I would recommend to start your tests with a sine generator sketch and not with something as complicated as A2DP...

Replies: 3 comments 3 replies

Comment options

if cfg.is_master = false; then the ESP32 expects that the values for pin_bck and pin_ws are provided by the external system.
If this is not working I would suggest to look for the issue on the Audio DSP side.

I have never tried but I doubt that this is also working for the pin_mck.

In any case I would recommend to start your tests with a sine generator sketch and not with something as complicated as A2DP...

You must be logged in to vote
2 replies
Comment options

Thanks for the really quick answer.

I fed the ESP32 with the LRClock (48kHz, Pin14) and the BitClock (around 3,07MHz, Pin15) from the DSP.
Signals look OK on the scope.

There is no serial audio data on the data pin of the I2S on the ESP32 (Pin 13).

Bluetooth from my phone is connected and streaming audio.
Edit: the line "cfg.is_master = false;" is active and uploaded.

Comment options

Hi! I had the same issue and managed to make it work:

  1. 3Mhz bit clock for stereo 48kHz sampling means that ESP must be configurred to output 32bit per sample
  2. not sure why, but experimenting with the configI noticed that use_apll must be true and buffer size must be "reasonable" (see below example, if value exceeded certain threshod data just didn't flow)
  3. BT provided 44100kHz and 16bit depth so I had to resample it and scale up (shift by 16 bit) because Adau does not support 32bit (only 16,20,24), datasheet states that it just ignores the remaining bits.
  4. When Adau is master, you must connect word select (MP10 to MP4) and bit clocks (MP11 to MP5) (according to the datasheet)
  5. Configure MP0 as DIN_0
image 7. Use 3 and 4 outputs as digital ones: image

Below is and example of sinwave:


#include <Arduino.h>
AudioInfo to_info(48000, 2, 32);
void setup() {
 Serial.begin(921600);
 Serial.setDebugOutput(true);
 Serial.print("hello!");
 Serial.printf("Flash chip size: %u bytes\n", ESP.getFlashChipSize());
 Serial.printf("Free DMA-capable heap: %d bytes\n", heap_caps_get_free_size(MALLOC_CAP_DMA));
 Serial.printf("Free total heap: %d bytes\n", ESP.getFreeHeap());
auto cfg = i2s.defaultConfig();
 cfg.copyFrom(to_info);
 cfg.pin_bck = GPIO_NUM_26;//14
 cfg.pin_ws = GPIO_NUM_25; //15
 cfg.pin_data = GPIO_NUM_22;
 cfg.use_apll = true;
 cfg.buffer_count = 6; // 16 does not work!
 cfg.buffer_size = 512;
 cfg.is_master = false;
 cfg.channels = 2;
 bool i2sinitialized= i2s.begin(cfg);
 if(!i2sinitialized){
 Serial.println("Failed to initialize I2S!");
 while (true) { }
 }
}
#include <math.h>
#define SAMPLE_RATE 48000
#define TONE_FREQ 400
#define CYCLE_SAMPLES ((SAMPLE_RATE / TONE_FREQ)) // Must be integer!
#define AMPLITUDE 10000 //up to 16k
int32_t buffer[CYCLE_SAMPLES * 2]; // Stereo: L + R
void generate_wave_buffer() {
 for (int i = 0; i < CYCLE_SAMPLES; i++) {
 double phase = (2.0f * M_PI * i) / CYCLE_SAMPLES;
 double sample_f = (sinf(phase)+1)/2;
 int32_t sample = ((int32_t)(sample_f * AMPLITUDE)) << 16; //adau compatibility hack
 buffer[2 * i] = sample; // Left
 buffer[2 * i + 1] = sample; // Right (or 0 if silence on R)
 }
}
void loop() {
 generate_wave_buffer();
 while (true) {
 size_t bytes_written = 0;
 i2s_write(I2S_NUM_0, buffer, sizeof(buffer), &bytes_written, portMAX_DELAY);
 }
}
Answer selected by pschatzmann
Comment options

You can try to log the result length of the data which is written to i2s, just to make sure that the write is really working.

To be honest I never tried this scenario - only one where an external DAC was the master and providing the data to the ESP32, but I would be really surprised if the ESP32 would not support this...

ps. Do you get the same frequencies if you use the ESP32 as Master?

You must be logged in to vote
1 reply
Comment options

Everything seems right - only not the output of signals ;)

There is this configuration thing, that initializes with:

I2SStream i2s;

and later does the setup:

auto cfg = i2s.defaultConfig();
...
i2s.begin(cfg);

There you can set most of the I2S pins like

cfg.pin_data = 13;
cfg.pin_ws = 14;
cfg.pin_bck = 15;

In the Espressif docs there is also a master clock pin.
Does this also exist in the cfg. config - someting like this?

cfg.pin_mclk = 3; //or cfg.pin_mck = 3;

I tried also something like

i2s.i2s_set_pin(3, mck_io_num); //this is out of espressifs doku

but with no success.

Comment options

That would be the pin_mck from my second last answer - and as I have mentioned I would be surprised if that would be supported as input. Let me know about your findings

You must be logged in to vote
0 replies
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Category
Q&A
Labels
None yet

AltStyle によって変換されたページ (->オリジナル) /