Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

MCLK CLOCK problem #955

Open
Marcin-Fenger opened this issue Jan 20, 2025 · 7 comments
Open

MCLK CLOCK problem #955

Marcin-Fenger opened this issue Jan 20, 2025 · 7 comments

Comments

@Marcin-Fenger
Copy link

Marcin-Fenger commented Jan 20, 2025

Version 3.0.13v I2s config

m_i2s_chan_cfg.id = (i2s_port_t)m_i2s_num; // I2S_NUM_AUTO, I2S_NUM_0, I2S_NUM_1
m_i2s_chan_cfg.role = I2S_ROLE_MASTER; // I2S controller master role, bclk and lrc signal will be set to output
m_i2s_chan_cfg.dma_desc_num = 16; // number of DMA buffer
m_i2s_chan_cfg.dma_frame_num = 512; // I2S frame number in one DMA buffer.
m_i2s_chan_cfg.auto_clear = true; // i2s will always send zero automatically if no data to send
i2s_new_channel(&m_i2s_chan_cfg, &m_i2s_tx_handle, NULL);

m_i2s_std_cfg.slot_cfg                = I2S_STD_PHILIPS_SLOT_DEFAULT_CONFIG(I2S_DATA_BIT_WIDTH_16BIT, I2S_SLOT_MODE_STEREO); // Set to enable bit shift in Philips mode
m_i2s_std_cfg.gpio_cfg.bclk           = I2S_GPIO_UNUSED;           // BCLK, Assignment in setPinout()
m_i2s_std_cfg.gpio_cfg.din            = I2S_GPIO_UNUSED;           // not used
m_i2s_std_cfg.gpio_cfg.dout           = I2S_GPIO_UNUSED;           // DOUT, Assignment in setPinout()
m_i2s_std_cfg.gpio_cfg.mclk           = I2S_GPIO_UNUSED;           // MCLK, Assignment in setPinout()
m_i2s_std_cfg.gpio_cfg.ws             = I2S_GPIO_UNUSED;           // LRC,  Assignment in setPinout()
m_i2s_std_cfg.gpio_cfg.invert_flags.mclk_inv = false;
m_i2s_std_cfg.gpio_cfg.invert_flags.bclk_inv = false;
m_i2s_std_cfg.gpio_cfg.invert_flags.ws_inv   = false;
m_i2s_std_cfg.clk_cfg.sample_rate_hz = 44100;
m_i2s_std_cfg.clk_cfg.clk_src        = I2S_CLK_SRC_APLL;        // Select PLL_F160M as the default source clock
m_i2s_std_cfg.clk_cfg.mclk_multiple  = I2S_MCLK_MULTIPLE_512;      // mclk = sample_rate * 256
i2s_channel_init_std_mode(m_i2s_tx_handle, &m_i2s_std_cfg);
I2Sstart(m_i2s_num);
m_sampleRate = 44100;

Works fine and in streams with samplerate 44100 mclk is 22MHz -> that is OK

Version 3.1.0a I2s config

m_i2s_num = i2sPort; // i2s port number

// -------- I2S configuration -------------------------------------------------------------------------------------------
m_i2s_chan_cfg.id            = (i2s_port_t)m_i2s_num;  // I2S_NUM_AUTO, I2S_NUM_0, I2S_NUM_1
m_i2s_chan_cfg.role          = I2S_ROLE_MASTER;        // I2S controller master role, bclk and lrc signal will be set to output
m_i2s_chan_cfg.dma_desc_num  = 32;
m_i2s_chan_cfg.dma_frame_num = 256;                    // I2S frame number in one DMA buffer.
m_i2s_chan_cfg.auto_clear    = true;                   // i2s will always send zero automatically if no data to send
i2s_new_channel(&m_i2s_chan_cfg, &m_i2s_tx_handle, NULL);

m_i2s_std_cfg.slot_cfg                = I2S_STD_PHILIPS_SLOT_DEFAULT_CONFIG(I2S_DATA_BIT_WIDTH_16BIT, I2S_SLOT_MODE_STEREO); // Set to enable bit shift in Philips mode
m_i2s_std_cfg.gpio_cfg.bclk           = I2S_GPIO_UNUSED;           // BCLK, Assignment in setPinout()
m_i2s_std_cfg.gpio_cfg.din            = I2S_GPIO_UNUSED;           // not used
m_i2s_std_cfg.gpio_cfg.dout           = I2S_GPIO_UNUSED;           // DOUT, Assignment in setPinout()
m_i2s_std_cfg.gpio_cfg.mclk           = I2S_GPIO_UNUSED;           // MCLK, Assignment in setPinout()
m_i2s_std_cfg.gpio_cfg.ws             = I2S_GPIO_UNUSED;           // LRC,  Assignment in setPinout()
m_i2s_std_cfg.gpio_cfg.invert_flags.mclk_inv = false;
m_i2s_std_cfg.gpio_cfg.invert_flags.bclk_inv = false;
m_i2s_std_cfg.gpio_cfg.invert_flags.ws_inv   = false;
m_i2s_std_cfg.clk_cfg.sample_rate_hz = 44100;
m_i2s_std_cfg.clk_cfg.clk_src        = I2S_CLK_SRC_APLL;        // Select PLL_F160M as the default source clock
m_i2s_std_cfg.clk_cfg.mclk_multiple  = I2S_MCLK_MULTIPLE_512;      // mclk = sample_rate * 256
i2s_channel_init_std_mode(m_i2s_tx_handle, &m_i2s_std_cfg);
I2Sstart(m_i2s_num);
m_sampleRate = 44100;

MCLK is duble -> 49MHz. I know that You change buffers number and size but that does not metter. I can change to I2S_MCLK_MULTIPLE_256 and solve the problem but could you check it out why the mclk is double in this version? Should be 22Mhz not 49Mhz.

BTW You can return old I2S config for IDF4.4 to compile the project on 4.4 :)

Arduino [email protected] ESP32 n16r8

@enjoyneering
Copy link

According to IDF help I2S_MCLK_MULTIPLE_256 is the correct value

The field i2s_std_clk_config_t::mclk_multiple indicates the multiple of MCLK to the sample rate. In most cases, I2S_MCLK_MULTIPLE_256 should be enough. However, if slot_bit_width is set to I2S_SLOT_BIT_WIDTH_24BIT, to keep MCLK a multiple to the BCLK, i2s_std_clk_config_t::mclk_multiple should be set to multiples that are divisible by 3 such as I2S_MCLK_MULTIPLE_384. Otherwise, WS will be inaccurate.

@Marcin-Fenger
Copy link
Author

According to IDF help I2S_MCLK_MULTIPLE_256 is the correct value

The field i2s_std_clk_config_t::mclk_multiple indicates the multiple of MCLK to the sample rate. In most cases, I2S_MCLK_MULTIPLE_256 should be enough. However, if slot_bit_width is set to I2S_SLOT_BIT_WIDTH_24BIT, to keep MCLK a multiple to the BCLK, i2s_std_clk_config_t::mclk_multiple should be set to multiples that are divisible by 3 such as I2S_MCLK_MULTIPLE_384. Otherwise, WS will be inaccurate.

It's not the case. 44.100 x 256 = 11.289 but output on oscilocope is 22Mhz. It's not good for this samplerate. BTW I find better sound quality with x512 and oversampling set to 128. Default is 64 - max for x256 multiple. So... Use 512, but in new library version give me 49Mhz instead 22MHz at 44100, You know.

@DifficultyToCreatName DifficultyToCreatName marked this as a duplicate of #951 Jan 22, 2025
@Marcin-Fenger
Copy link
Author

I return to 3.013v and something change - m_i2s_std_cfg.clk_cfg.mclk_multiple = I2S_MCLK_MULTIPLE_256 suddenly has the same behavior. I have to change to 256 from 512 for 22Mhz. I think the problem is new framework.

@enjoyneering
Copy link

What is your XTAL frequency? Are you using ESP32 at 160MHz or 250MHz?

@Marcin-Fenger
Copy link
Author

XTAL frequency

board_build.f_cpu = 240000000L
board_build.f_xtal = 40000000L

Still is double but it is not a big deal. I have set half and now it is working as expected. It's IDF 5.3.2 issue I think so.

@enjoyneering
Copy link

enjoyneering commented Jan 27, 2025

try to change "m_i2s_std_cfg.clk_cfg.clk_src" from "I2S_CLK_SRC_DEFAULT" to "SOC_MOD_CLK_XTAL" or "SOC_MOD_CLK_PLL_F240M"

By the way, SCLK (Serial clock) and MCLK (Master clock frequency) are not the same thing. This library uses 3-wire I2S connection type. The MCLK is generated by the audio codec (silicon chip) to time and/or drive its own internal operation. Values in the range of 10-60MHz are pretty typical (50MHz max for PCM5102).

PCM5102:
SCL= I2S MCLK (Master clock frequency)*
BCK=I2S SCLK (Serial clock)
DIN=I2S SD (Serial data)
LRCK=I2S WS (Word select)

*The system clock PLL mode allows designers to use a simple 3-wire I2S audio source. The 3-wire source reduces the need for a high frequency SCK, making PCB layout easier, and reduces high frequency electromagnetic interference. The device starts up expecting an external SCK input, but if BCK and LRCK start correctly while SCK remains at ground level for 16 successive LRCK periods, then the internal PLL starts automatically generating an internal SCK from the BCK reference. Specific BCK rates are required to generate an appropriate master clock. Table 11describes the minimum and maximum BCK per LRCK for the integrated PLL to automatically generate an internal SCK.

Image

So, to get a correctly generated MCLK by the audio codec, we need to generate a correct SCLK:

.sample_rate_hz = 44100
.data_bit_width = 16
.slot_mode = 2

SCLK=.sample_rate_hz * .data_bit_width * .slot_mode = 1.411MHz

Image

@Marcin-Fenger
Copy link
Author

try to change "m_i2s_std_cfg.clk_cfg.clk_src" from "I2S_CLK_SRC_DEFAULT" to "SOC_MOD_CLK_XTAL" or "SOC_MOD_CLK_PLL_F240M"

We are in Arduino 3.1.1 & IDF 5.3.2 environment.

For m_i2s_std_cfg.clk_cfg.clk_src we have only 3 options:
I2S_CLK_SRC_DEFAULT
I2S_CLK_SRC_PLL_160M
I2S_CLK_SRC_APLL

"SOC_MOD_CLK_XTAL" or "SOC_MOD_CLK_PLL_F240M" does not work.

I do use last one becouse of low jitter. Previous version [email protected] and version [email protected] works well and multiplier x256 = 12MHz MCLK. I play with it for a long time and it is not my very first project, you know. We talk only about MCLK.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants