-
Notifications
You must be signed in to change notification settings - Fork 7k
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
Unable to set I2S APLL Clock for 48khz 32bit 2ch (IDFGH-432) #2634
Comments
For who is interested in setting up manually the APLL Clock (setting up manually odir, sdm0, sdm1, sdm2) I made this not really nice C program but maybe could be useful for someone and could be a starting point to make a better APLL setup procedure:
Said so, I'm not sure that in case I2S is in Slave mode, setting up a apll frequency by hand it's useful at all.. but maybe in Master mode? |
@pad52 Thank you for this code snippet, I will be trying this out for my I2S master - I have not been able to get the exact APLL frequency I needed either at 48kHz, I had to use 44.1kHz to get a frequency multiple that my I2S codec could support. (i.e. 384x) |
I tried the code to search all possible APLL parameters at various sampling rates and have arrived at a startling conclusion: the APLL inside the ESP32 can only usefully support 44.1kHz and that 16934400hz is the only useful frequency that the APLL can generate for driving the MCLK on I2S codecs (44.1k x384). |
Hey, try to set this values at the end of the function i2s_apll_calculate_fi2s() in esp-idf/components/drivers/i2s.c or sdm0= 40, sdm1= 15, sdm2= 7, odir= 4 |
Almost the same problem here. Using a ALB32-WROVER running IDF v3.0.6, reading a 2-channel 32-bit 48 kHz signal in slave mode, I see the following: The I2S log says: I2S: APLL: Req RATE: 48000, real rate: 43945.016, BITS: 32, CLKM: 1, BCK: 8, MCLK: 12292917.167, SCLK: 2812481.000000, diva: 1, divb: 0 The exact same software (and signal) using IDF v3.1.1 shows: In this case the I2S log shows: I2S: PLL_D2: Req RATE: 48000, real rate: 48076.000, BITS: 32, CLKM: 13, BCK: 4, MCLK: 12292917.167, SCLK: 3076864.000000, diva: 64, divb: 1 Tried different settings for use_appl but didn't see any change. |
Seems I was to quick to complain here. With use_appl = true, this works on both IDF v3.0.x and v3.1.1, |
Here is the I2S driver modification I made last year: APLL should get within < 10 ppm. If the problem still exists in esp-idf, perhaps someone should replace i2s_apll_calculate_fi2s with this version. For example:
|
Try the attached patch. It has solved the inaccurate apll clock rate issue. The patch is w.r.t. latest IDF i.e. 4.0. Kindly share the result after trial. The percentage difference between required sample rate and apll_clock_rate is 0.001. |
it is still incorrect for 176400/2/16. The algorithm selects sdm2=7,odir=1,sdm1=sdm0=255 which gives 156249 where sdm2=5,odir=0,sdm1=2,sdm0=222 would have given precisely 176400. I guess we need to either iterate more than once (re-consider odir when accuracy is not reached) or have a different first pass on sdm2 selection. Could not find a good solution yet, with minimal changes. |
I can propose that which, although not very elegant, does the job for me in all cases and in less steps as well. It probably assumes the function knows too much about the PLL though ...
|
Did you try my version listed above? Or is it the new version igrr pushed recently? |
No I did not I thought it was the same as the current version but now I see the difference. It still bothers me that we iterate so many loops where we can shoot approximatively to the right place. |
Mine was only a simple patch to the original version, was just wondering if it gets you 176400. What application are you running that freq for? |
it's for spdif direct connection, by convincing the i2s driver to be used as a spdif interface. But you need 32 bits per sample and 2x rate because it's BMC encoded. So 44.1 requires a 176.4kHz/16 clock |
Hi @fknrdcls, I tried your version listed above but I could only get 162760.422:
|
That's off by a fair amount, it must be odir that's out I guess. Does your code provided above work for all the common clock rates as well as 176400? If you could add comments to the code I can test it as per igrr's testing method and then maybe we should submit a pull request once it's been standardised as per the espressif style guide. I'm interested in some of your work, I like your idea of pushing spdif out via the I2S peripheral. |
@fknrdcls , @philippe44 's code test results are as follows:
|
I think 176k @ 16bits is the maximum that can be done, taking into account various constraints.
|
Code mainly comes from here https://github.com/FrankBoesing/Teensy3-SPDIF |
Environment
Problem Description
In I2S Slave TX mode
i2s_mode_t mode = I2S_MODE_SLAVE | I2S_MODE_TX; i2s_comm_format_t comm_fmt = I2S_COMM_FORMAT_I2S | I2S_COMM_FORMAT_I2S_MSB;
If I set a frequency of 48Khz and APLL, it will not set the frequency correctly and I got audio problems, I imagine is because of DMA buffer under/overrun.
I (352) phy: phy_version: 4000, b6198fa, Sep 3 2018, 15:11:06, 0, 2 I (902) I2S: queue free spaces: 1 I (912) I2S: DMA Malloc info, datalen=blocksize=4088, dma_buf_count=16 I (912) I2S: APLL: Req RATE: 48000, real rate: 43945.238, BITS: 32, CLKM: 1, BCK_M: 8, MCLK: 22499962.000, SCLK: 2812495.250000, diva: 1, divb: 0 I (932) BT_APP_CORE: bt_app_task_handler, sig 0x1, 0x0 I (932) main: RAM left 75544
If I disable APLL, then the frequency is correctly set - but I get crappy sound due to fractional PLL.
In case I set mclk_fixed (at 24573600.000) I get 50Khz:
I (781) I2S: queue free spaces: 1 I (781) I2S: DMA Malloc info, datalen=blocksize=4088, dma_buf_count=16 I (791) I2S: APLL: Req RATE: 48000, real rate: 50223.129, BITS: 32, CLKM: 1, BCK_M: 7, MCLK: 22499962.000, SCLK: 2812495.250000, diva: 1, divb: 0 I (801) BT_APP_CORE: bt_app_task_handler, sig 0x1, 0x0 I (811) main: RAM left 75668
I imagine that the problem could be in function
i2s_apll_calculate_fi2s
that have a bad behaviour in case of 48Khz 32bit 2ch.
this issue could be related
Then further investigation get me through an error in the documentation:
APLL_MAX_FREQ = 500Mhz and
APLL_MIN_FREQ = 250 Mhz
but in the description of we read:
* The dividend in this expression should be in the range of 240 - 600 MHz.
and
* 1. We will choose the parameters with the highest level of change,
* With 350MHz<fout<500MHz, we limit the sdm2 from 4 to 9,
What's the trouth?
Steps to reproduce
Take A2DP_Sink Example and set I2S at 48Khz, Slave, 32Bit.
The text was updated successfully, but these errors were encountered: