Hi, Jan,
As you described that the codec generates noise when the core/system frequency exceeds 168mHz, I suppose that the bit clock frequency of codec is incorrect.
I have checked both the code and the schematics of TWR-Audio-SGTL board, the SGTL5000 codec works in slave mode and synchronous mode, in other words, the Kinetis I2S interface genertates both the bit clock and frame clock, the receiver/transmitter of the codec use the same frame/bit clock. It also means that the core/system clock generates the bit/frame clock by a divider, the divider is only specified by the I2Sx_MDR.
for example, if you use 168MHz core/ssytem clock, the bit clock frequency is 32*2*16K=1.024MHz(sampling frequency is 16KHz), the diviedr should be 168MHz/1.024Mhz=164;
I suggest you set the core/system clock in 172MHz, in the case, if the set the divider as 168, the bit clcok will be 1.024Mhz approximatively.
I think you can write the I2Sx_MDR register dierctly with the code in SAI_SetMasterClockDivider() in fsl_sai.c:
/* Fill the computed fract and divider to registers */
base->MDR = I2S_MDR_DIVIDE(167); /// | I2S_MDR_FRACT(current_fract - 1);
If you want to research the divider, pls read the the function I pasted in fsk_sai.c, but the code is not easy to understand:
You can also check the I2S_MDR register value in debugger.
Hope it can help you.
BR
Xiangjun rong
static void SAI_SetMasterClockDivider(I2S_Type *base, uint32_t mclk_Hz, uint32_t mclkSrcClock_Hz)
{
uint32_t freq = mclkSrcClock_Hz;
uint16_t fract, divide;
uint32_t remaind = 0;
uint32_t current_remainder = 0xFFFFFFFFU;
uint16_t current_fract = 0;
uint16_t current_divide = 0;
uint32_t mul_freq = 0;
uint32_t max_fract = 256;
/*In order to prevent overflow */
freq /= 100;
mclk_Hz /= 100;
/* Compute the max fract number */
max_fract = mclk_Hz * 4096 / freq + 1;
if (max_fract > 256)
{
max_fract = 256;
}
/* Looking for the closet frequency */
for (fract = 1; fract < max_fract; fract++)
{
mul_freq = freq * fract;
remaind = mul_freq % mclk_Hz;
divide = mul_freq / mclk_Hz;
/* Find the exactly frequency */
if (remaind == 0)
{
current_fract = fract;
current_divide = mul_freq / mclk_Hz;
break;
}
/* Closer to next one, set the closest to next data */
if (remaind > mclk_Hz / 2)
{
remaind = mclk_Hz - remaind;
divide += 1;
}
/* Update the closest div and fract */
if (remaind < current_remainder)
{
current_fract = fract;
current_divide = divide;
current_remainder = remaind;
}
}
/* Fill the computed fract and divider to registers */
base->MDR = I2S_MDR_DIVIDE(current_divide - 1) | I2S_MDR_FRACT(current_fract - 1); //Rong wrote, change the value here directly
/* Waiting for the divider updated */
while (base->MCR & I2S_MCR_DUF_MASK)
{
}
}
#endif /* FSL_FEATURE_SAI_HAS_MCLKDIV_REGISTER */