Edit

IABSD.fr/xenocara/driver/xf86-video-intel/src/scripts/tv.5c

Branch :

  • Show log

    Commit

  • Author : matthieu
    Date : 2009-06-25 20:16:43
    Hash : 42b052b9
    Message : update to xf86-video-intel 2.7.1. Tested by many.

  • driver/xf86-video-intel/src/scripts/tv.5c
  • /*
     * 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 ();