129 lines
3.1 KiB
Plaintext
129 lines
3.1 KiB
Plaintext
/*
|
|
* 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 ();
|