/*
(c) Frank Bösing
Sketch to calculate I2S FRACT / DIVIDE values
*/
/* Quote from manual:
The MCLK fractional clock divider uses both clock edges from the input clock to
generate a divided down clock that will approximate the output frequency, but without
creating any new clock edges. Configuring FRACT and DIVIDE to the same value will
result in a divide by 1 clock, while configuring FRACT higher than DIVIDE is not
supported. The duty cycle can range from 66/33 when FRACT is set to one less than
DIVIDE down to 50/50 for integer divide ratios, and will approach 50/50 for large noninteger
divide ratios. There is no cycle to cycle jitter or duty cycle variance when the
divide ratio is an integer or half integer, otherwise the divider output will oscillate
between the two divided frequencies that are the closest integer or half integer divisors of
the divider input clock frequency. The maximum jitter is therefore equal to half the
divider input clock period, since both edges of the input clock are used in generating the
divided clock.
*/
const float pllfreqs[] = {16000000, 72000000, 96000000, 120000000, 144000000, 168000000, 180000000, 192000000, 216000000, 240000000};
const float samplefreqs[] = { 8000, 11025, 16000, 22050, 32000, 44100, 44117.64706 , 48000, 88200, 44117.64706 * 2, 96000, 176400, 44117.64706 * 4, 192000/*, 200000, 210000, 220000, 230000, 240000, 250000, 260000, 270000, 280000, 290000, 300000*/};
const int numpll = sizeof(pllfreqs) / sizeof(float);
const int numfreqs = sizeof(samplefreqs) / sizeof(float);
void calc(const float pll, const float freq) {
float p = pll / 256.0;
float err = 1e6;
int mu = 0;
int di = 0;
for (int m = 1; m < 256 ; m++) {
for (int d = m; d < 4096; d++) {
float f = (p * m) / d;
float e = fabs(freq - f);
if (e < err) {
mu = m;
di = d;
err = e;
}
}
}
#if 1
Serial.printf("{%d, %d}", mu, di);
#else
Serial.printf("{%d, %d /* %.1fHz */}", mu, di, (pll * mu / di) / 256.0);
#endif
}
void setup() {
delay(1000);
Serial.printf("const int numfreqs = %d;\n", numfreqs);
Serial.print("const int samplefreqs[numfreqs] = {");
for (int p = 0; p < numfreqs; p++)
Serial.printf("%.0f%s", samplefreqs[p], (p < numfreqs - 1) ? ", " : " " );
Serial.println("};");
Serial.println();
for (int p = 0; p < numpll; p++) {
Serial.printf("#%s (F_PLL==%.0f)\n", p == 0 ? "if" : "elif", pllfreqs[p] );
Serial.printf(" const tmclk clkArr[numfreqs] = {");
for (int s = 0; s < numfreqs; s++) {
calc(pllfreqs[p], samplefreqs[s]);
if (s < numfreqs - 1) Serial.print(", ");
}
Serial.println("};");
}
Serial.println("#endif");
}
void loop() {}