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
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
|
/*
* tv.5c
*
* Compute tv encoder subcarrier dda constants
*
* The TV encoder subcarrier must be set precisely to the
* required frequency or the cumulative phase errors will be
* quite visible in the output. To accomplish this, the TV encoder
* has a complex circuit that takes a fixed clock, generated by the PLL
* and generates a precise subcarrier clock from that using the following
* formula:
*
* subcarrier = pixel_clock * (S1 + (S2 + (S3/Z3)) / Z2) / 4096
*
* Careful selection of the constants will provide the necessarily
* precise clock.
*
* In the code below, S1 is represented by dda1, S2/Z2 by dda2 and S3/Z3
* by dda3.
*/
typedef struct {
int step;
int size;
} term_t;
/*
* Find the approximation closest, but no larger than 'v', where
* 0 <= v < 1, and the result denominator must be less than 30000.
*/
term_t approx (rational v)
{
rational best_dist = 1.0;
term_t best;
for (int den = 20000; den < 30000; den++)
{
int num = floor (v * den);
term_t approx = { step = num, size = den };
rational dist = v - approx.step/approx.size;
if (dist >= 0 && dist < best_dist)
{
best_dist = dist;
best = approx;
}
}
return best;
}
typedef struct {
rational subcarrier;
rational pixel;
rational result;
term_t dda1;
term_t dda2;
term_t dda3;
} dda;
/*
* Compute the dda constants for the given pixel clock and
* desired subcarrier frequency
*/
dda find_dda (rational pixel, rational subcarrier)
{
dda d;
d.subcarrier = subcarrier;
d.pixel = pixel;
rational dda1 = subcarrier / pixel * 4096;
d.dda1 = (term_t) { step = floor (dda1), size = 4096 };
rational dda2 = dda1 - d.dda1.step;
d.dda2 = approx (dda2);
rational dda3 = dda2 * d.dda2.size - d.dda2.step;
d.dda3 = approx (dda3);
/* Compute the resulting pixel clock to compare */
d.result = d.pixel * (d.dda1.step +
(d.dda2.step + d.dda3.step/d.dda3.size) /
d.dda2.size) / d.dda1.size;
return d;
}
/*
* Print out the computed constants
*/
void print_dda (dda d)
{
printf ("\t/* desired %9.7f actual %9.7f clock %g */\n",
d.subcarrier, d.result, d.pixel);
printf ("\t.dda1_inc\t= %6d,\n", d.dda1.step);
printf ("\t.dda2_inc\t= %6d,\t.dda2_size\t= %6d,\n",
d.dda2.step, d.dda2.step != 0 ? d.dda2.size : 0);
printf ("\t.dda3_inc\t= %6d,\t.dda3_size\t= %6d,\n",
d.dda3.step, d.dda3.step != 0 ? d.dda3.size : 0);
}
/*
* These are all of the required subcarrier frequencies
*/
rational[] subcarriers = {
/* these are the values we use; for some reason, this generates
* a more stable image (at least for NTSC) */
3.580, 4.434, 3.582, 3.576, 4.430,
/* these are the values pulled out of the various specs */
3.579545, 4.433618, 3.582056, 3.575611, 4.433618
};
/*
* We fix the pixel clock to a value which the hardware can
* generate exactly
*/
rational pixel = 107.520;
void main ()
{
for (int i = 0; i < dim(subcarriers); i++)
{
dda d = find_dda (pixel, subcarriers[i]);
print_dda (d);
}
}
main ();
|