kendryte / kendryte-freertos-sdk

This project is no longer maintained Not recommended for product development.
Apache License 2.0
201 stars 67 forks source link

I2S SCLK Setting sometime may fail? #25

Closed touchtzou closed 5 years ago

touchtzou commented 5 years ago

BUG REPORT

Expected behavior

In order to set I2S2 WS to 48KHz, SCLK to 3.072MHz, I Set the PLL2 Clock to 36864000Hz.

Actual behavior

The returned PLL2 clock is 36833333Hz, however WS is about 57.5kHz, it looks like the i2s.c driver is not correct.

Test code

Since the acutal clock of PLL2 cannot perfectly match the setting value. When the actual value is less than the setting value. The equation may get wrong result. threshold = pll2_clock / (format->sample_rate 128) - 1; We need to use float math function to get closer result. threshold = round(1.0f pll2_clock / (format->sample_rate * 128) - 1);

The code in I2S.c: static void extract_params(const audio_format_t format, uint32_t threshold, i2s_word_select_cycles_t wsc, i2s_word_length_t wlen, size_t block_align, uint32_t dma_divide16) { uint32_t pll2_clock = 0; pll2_clock = sysctl_pll_get_freq(SYSCTL_PLL2); configASSERT((format->sample_rate > pll2_clock / (1 << 23)) && (format->sample_rate < pll2_clock / (1 << 7))); switch (format->bits_per_sample) { case 16: wsc = SCLK_CYCLES_32; wlen = RESOLUTION_16_BIT; block_align = format->channels 2; dma_divide16 = 1; break; case 24: wsc = SCLK_CYCLES_32; wlen = RESOLUTION_24_BIT; block_align = format->channels 4; dma_divide16 = 0; break; case 32: wsc = SCLK_CYCLES_32; wlen = RESOLUTION_32_BIT; block_align = format->channels 4; *dma_divide16 = 0; break; default: configASSERT(!"Invlid bits per sample"); break; } // Fix Bug since the actual pll is not equal to set value. 2018/10/19

if 0

*threshold = pll2_clock / (format->sample_rate * 128) - 1;

else

threshold = round(1.0f pll2_clock / (format->sample_rate * 128) - 1);

endif

}

sunnycase commented 5 years ago

This bug has already been fixed in 950a9238861d3a1eb8f5a3206dae47c21b35f479.