Page 1 of 1

PDM-mode of I2S peripheral through i2s driver

Posted: Fri Dec 15, 2017 2:45 pm
by michaelwgnr
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!

Re: PDM-mode of I2S peripheral through i2s driver

Posted: Fri Dec 15, 2017 5:46 pm
by ESP_tuanpm
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.

Re: PDM-mode of I2S peripheral through i2s driver

Posted: Mon Dec 18, 2017 1:23 pm
by michaelwgnr
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

Re: PDM-mode of I2S peripheral through i2s driver

Posted: Tue Dec 19, 2017 7:41 am
by michaelwgnr
Has anyone gotten PDM to run? Could they share their code?

Re: PDM-mode of I2S peripheral through i2s driver

Posted: Tue Jan 16, 2018 3:48 pm
by moddsie
Just following up on this. Has anyone been successful in getting PDM working?

Re: PDM-mode of I2S peripheral through i2s driver

Posted: Wed Jan 17, 2018 7:41 am
by michaelwgnr
Yes, I have been successful. My main issue ended up being a silly mix-up between number-of-samples and buffer size which I haven't discovered for the whole of two days or so... So I skipped half of the data that I was supposed to feed to the driver, which of course resulted in some terrible... "noise".

PDM-mode generally seems to work. But for using the APLL, I needed to modify the APLL clock configuration in the i2s driver... Unfortnuately, I only managed to get it right for one sampling rate, so... I hope the driver will be fixed soon.

Also, I would still be happy for any clarification on this:
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?

Cheers,
-mike

Re: PDM-mode of I2S peripheral through i2s driver

Posted: Tue Jun 30, 2020 7:02 am
by vibro_tech
Just following up. Has anyone success with PDM mic working?

Re: PDM-mode of I2S peripheral through i2s driver

Posted: Sun Apr 30, 2023 4:48 pm
by lladam
vibro_tech wrote:
Tue Jun 30, 2020 7:02 am
Just following up. Has anyone success with PDM mic working?
Hi Mike.
Would you like to share your code?
Thanks