PDM-mode of I2S peripheral through i2s driver

michaelwgnr
Posts: 25
Joined: Wed Dec 21, 2016 3:41 pm

PDM-mode of I2S peripheral through i2s driver

Postby michaelwgnr » Fri Dec 15, 2017 2:45 pm

Hello there,

I've got an audio amplifier chip attached to the Rev. 1 ESP32 and I'm trying to get the PDM-mode of the i2s mode running without success so far. There are several things I struggle with and somehow no sound seems to emerge from my speakers, even though I tried multiple different combinations of parameters... I'm trying to get it to work with the i2s driver module i2s.c.

Here's what I do:

First, I initialize the module

Code: Select all

  const i2s_pin_config_t pdm_pin_cfg =
  {
    .bck_io_num   = I2S_PIN_NO_CHANGE,
    .ws_io_num    = PDM_CLK_PIN,
    .data_out_num = PDM_DATA_PIN,
    .data_in_num  = I2S_PIN_NO_CHANGE
  };
 
  i2s_config_t i2s_config = {
    .mode                 = I2S_MODE_MASTER | I2S_MODE_TX | I2S_MODE_PDM,
    .sample_rate          = 16000,
    .bits_per_sample      = I2S_BITS_PER_SAMPLE_16BIT,
    .channel_format       = I2S_CHANNEL_FMT_RIGHT_LEFT,
    .communication_format = I2S_COMM_FORMAT_PCM,
    .intr_alloc_flags     = ESP_INTR_FLAG_LEVEL1,
    .dma_buf_count        = 8,
    .dma_buf_len          = 64,
    .use_apll             = 1,
  };
 
  ESP_ERROR_CHECK( i2s_driver_install(I2S_PORT, &i2s_config, 0, NULL) );
  ESP_ERROR_CHECK( i2s_set_pin(I2S_PORT, &pdm_pin_cfg) );


This results in the following console output:

Code: Select all

I2S: APLL: Req RATE: 16000, real rate: 15999.001, BITS: 16, CLKM: 1, BCK: 8, MCLK: 5.208, SCLK: 511968.031250, diva: 1, divb:
0


So... the clock is running at 512kHz? I'm not sure about I2S, but concerning PDM, from my understanding - mainly from the datasheet of the amplifier - the PDM clock frequency for a sampling rate of 16kHz should be at 2.048MHz for 128x oversampled PDM. If I read the chapter 11.4.7 "I2S PDM" of the ESP32 Technical reference manual, if I understand this right, it says that the PDM-Frequency will always be 48x128kHz, i.e. 6.144MHz. That would correspond to an audio sampling rate of 48kHz.

Is this correct? Is the PDM mode of the I2S peripheral built such, that it will always output 48kHz audio at a PDM-clock-rate of 6.144MHz? If so, then the frequency calculation for the APLL in i2s.c is definitely wrong!

After the initialisation, I just continuously feed a sine wave. I'm not sure in what format (endianness) it has to be, but as long as I don't hear no sound at all, I don't really care if the PCM data is read out correctly.

Code: Select all


static const uint16_t mod_sin_table_a[] =
{
   32767, 37892, 42892, 47642, 52026, 55936, 59276, 61962,
   63930, 65130, 65534, 65130, 63930, 61962, 59276, 55936,
   52026, 47642, 42892, 37892, 32766, 27641, 22641, 17891,
   13507,  9597,  6257,  3571,  1603,   403,     0,   403,
    1603,  3571,  6257,  9597, 13507, 17891, 22641, 27641,
   
};

for(;;)
{
  assert(0 < i2s_write_bytes(I2S_PORT, (const char *)mod_sin_table_a, sizeof(mod_sin_table_a), portMAX_DELAY));
}


I also tried to use it without the audio PLL, but this seems to result in an extremely unstable clock (see trace below)!

Image

I'd be happy for any pointers on what to do to get PDM working! I urgently need it!

EDIT: Removed section about signals being out-of-phase, as that does not seem to be relevant.
EDIT 2: Okay, at least without APLL it seems to be working on the ESP32-side, I do also have a hardware problem here... Nonetheless, a fix for the APLL calculation would be great!
Last edited by michaelwgnr on Fri Dec 15, 2017 6:03 pm, edited 1 time in total.

tuanpm
Posts: 3
Joined: Sat Dec 05, 2015 7:59 am

Re: PDM-mode of I2S peripheral through i2s driver

Postby tuanpm » Fri Dec 15, 2017 5:46 pm

Due to reduced dependency parameters to speed up the apll calculation, the parameters

Code: Select all

I2S [i2s_num] -> clkm_conf.clkm_div_b = 0;
I2S [i2s_num] -> clkm_conf.clkm_div_a = 1;
I2S [i2s_num] -> sample_rate_conf.tx_bck_div_num = 8;
I2S [i2s_num] -> sample_rate_conf.rx_bck_div_num = 8;

is fixed when using apll

Meanwhile, when using PDM

Code: Select all

I2S [i2s_num] -> clkm_conf.clka_en = 0;
I2S [i2s_num] -> clkm_conf.clkm_div_a = 63;
I2S [i2s_num] -> clkm_conf.clkm_div_b = clkmDecimals;
I2S [i2s_num] -> clkm_conf.clkm_div_num = clkmInteger;
I2S [i2s_num] -> sample_rate_conf.tx_bck_div_num = bck;
I2S [i2s_num] -> sample_rate_conf.rx_bck_div_num = bck;


Parameters such as bck, clkmInteger are calculated when no apll is used. Apparently the i2s driver is having problems there
I will look for a proper calculation in this case.

michaelwgnr
Posts: 25
Joined: Wed Dec 21, 2016 3:41 pm

Re: PDM-mode of I2S peripheral through i2s driver

Postby michaelwgnr » Mon Dec 18, 2017 1:23 pm

Hi tuanpm,

Thanks for the response. This is about what I gathered from the sources as well. Still, I'd be happy if you could answer my question:
Is the PDM mode of the I2S peripheral built such, that it will always output 48kHz audio at a PDM-clock-rate of 6.144MHz?

Furthermore, I wonder if I'm feeding the samples right. Is Endianness and bit-depth in PDM-mode configurable? I just write the values, assuming little endian 16-bit values, but I'm not quite sure this is right.

Cheers,
-mike

michaelwgnr
Posts: 25
Joined: Wed Dec 21, 2016 3:41 pm

Re: PDM-mode of I2S peripheral through i2s driver

Postby michaelwgnr » Tue Dec 19, 2017 7:41 am

Has anyone gotten PDM to run? Could they share their code?

Who is online

Users browsing this forum: No registered users and 5 guests