summaryrefslogtreecommitdiff
path: root/tools/clkcalc.c
blob: cc5b9326ae40d18f69884ce39c6014867f82f58b (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
#include <stdio.h>
#include <stdint.h>

double _fabs(double a)
{
	return a<0?a*-1:a;
}

typedef struct {
	int pclkdiv_idx;
	int bitrate;
	int x;
	int y;
	double err;
} result_t;

static const int pclkdiv[] = { 1, 2, 4, 8 };


int main(int argc, char *argv[])
{
	result_t best;
	best.err = 999999;

	if(argc < 3) {
		printf("Usage: %s samplerate bitwidth channelcount\n", argv[0]);
		printf("Example: 48KHz 16bit stereo\n");
		printf("%s 48000 16 2\n", argv[0]);
		return 1;
	}

	int fs = atoi(argv[1]);
	int bw = atoi(argv[2]);
	int ch = atoi(argv[3]);

	int target = fs * bw * ch;

	int cclk = 100000000;

	result_t res;
	res.pclkdiv_idx = 3;

	res.bitrate = 0;
	res.x = 1;
	res.y = 1;

	for(;res.pclkdiv_idx >= 0; res.pclkdiv_idx--) {

		double clk = (cclk / pclkdiv[res.pclkdiv_idx]);

		for(res.y = 1; res.y < 256; res.y++) {

			double clk_y = clk / (double)res.y;

			// Note y must be greater than or equal to x.
			for(res.x = 1; res.x <= res.y; res.x++) {
			
				double clk_y_x_2 = (clk_y * (double)res.x) / 2.0;

				for(res.bitrate = 0; res.bitrate < 65; res.bitrate++) {

					double val = clk_y_x_2 / ((double)res.bitrate + 1.0);

					res.err = _fabs(val - target);
					if(res.err < best.err) best = res;

					if(res.err == 0.0) {
						goto found;
					}
				}
			}
		}
	}

	goto not_found;

 found:
	printf("Found:\n");
	printf(" pclkdiv: %d\n", pclkdiv[res.pclkdiv_idx]);
	printf(" bitrate: %d\n", res.bitrate);
	printf(" x: %d\n", res.x);
	printf(" y: %d\n", res.y);
	return 0;

 not_found:
	printf("Not found - best was:\n");
	printf(" pclkdiv: %d\n", pclkdiv[best.pclkdiv_idx]);
	printf(" bitrate: %d\n", best.bitrate);
	printf(" x: %d\n", best.x);
	printf(" y: %d\n", best.y);
	printf(" err: %f\n", best.err);
	return 1;
}