2019-11-06 11:29 PM
Hello
I am trying to establish I2S communication with external audio codec. The manual says the I2S clock (Fi2s_clk) is a function of the audio frequency. There is table with example frequencies. For example, the table provides 3 examples for frequency Fws = 48kHz, and possible Fi2s_clk are 12.288MHz, 49.152MHz, and 61.44Mhz. I was not able to get such frequencies with the CubeMX application (i am using HSE=25Mhz).
How can I configure the audio communication if I cannot set the right input clock for the I2S?
2019-11-07 05:59 AM
I had the same problem - Cube kept changing the dividers to random values even though someone showed me some fractional divide ratios that should work.
My assumption was that CubeMX doesn't work with the H7 so I am doing it by hand using the datasheet. But as I need different frequencies my code won't be much good to you. In any case for best performance you need to use an external 12.288MHz crystal which is about 20 cents.
2019-11-10 11:25 PM
So I fixed the problems and now I have a working codec (i am using TLV320AIC3204) with DMA.
I am going to share what I did for anywone who got here looking for answers.
1. Setting the I2S clock
I tried using cube to find a supported clock combination and it didn't provide. My audio is 44100 kHz and there was no supported clock. So I wrote a short script in Matlab to provide for me the available clock combinations nearest to what I needed. Matlab found some clocks that are approx. 0.01% from my target and that work well enough. Here is the code for anyone who needs such:
finput = 25000000; %HSE
ftarget = 41000; %audio frequency, Fws
divm2_range = [1 63];
divn2_range = [4 512];
divp2_range = [1 128];
target_multipliers = [1 18];
structmember = struct('diff_from_target' ,1000, "divm",0, "divn",0,"divp",0,"I2SDIV_ODD",0);
answers_arr = [structmember structmember structmember structmember structmember structmember structmember structmember structmember structmember structmember structmember structmember structmember structmember structmember structmember structmember];
for d1=divm2_range(1):divm2_range(2)
for d2=divn2_range(1):divn2_range(2)
for d3=divp2_range(1):divp2_range(2)
for t1=target_multipliers(1):1:target_multipliers(2)
if t1==3
continue;
end
normalized_multiplier = t1*256;
result = finput/d1*d2/d3/normalized_multiplier;
diff_from_target = abs(ftarget-result);
if diff_from_target<answers_arr(end).diff_from_target
answers_arr(end).diff_from_target = diff_from_target;
answers_arr(end).divm = d1;
answers_arr(end).divn = d2;
answers_arr(end).divp = d3;
answers_arr(end).I2SDIV_ODD = t1;
[x,idx]=sort([answers_arr.diff_from_target]);
answers_arr = answers_arr(idx);
end
end
end
end
end
2. Using the DMA
DMA should be used over the supported RAM regions for DMA0 or DMA1. DMA should be configured to
hdma_spi1_tx.Init.PeriphDataAlignment = DMA_PDATAALIGN_HALFWORD;
hdma_spi1_tx.Init.MemDataAlignment = DMA_MDATAALIGN_HALFWORD;
to support the required transaction speed.