/* * 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 ();