Logo Search packages:      
Sourcecode: videogen version File versions  Download package

videogen.c

/*
 * +-------------------------------------------------------+
 * |                                                       |
 * |     videogen                                          |
 * |                                                       |
 * |     a simple XFree86 Modeline calculator              |
 * |     (c) 1997-2002, Szabolcs Rumi                      |   
 * |                                                       |
 * |     http://www.rtfm.hu/videogen                       |
 * |                                                       |
 * |     the videogen package is distributed under the     |
 * |     GNU General Public License Version 2 (GPLv2)      |
 * |                                                       |
 * +-------------------------------------------------------+   
 */





#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
#include <string.h>
#include <math.h>

#include "config.h"
#include "videogen.h"





extern FILE *yyin;
extern int yyparse (void);
extern int yydebug;





char *cfgfile = CFG_CFGFILE;
unsigned int verbose = CFG_VERBOSE;
unsigned int fbset = CFG_FBSET;
unsigned int nvidia = CFG_NVIDIA;
unsigned int num_modes = 0;
resolution_t modes[256];
double max_dotclk = 0;
double max_hfreq = 0;
double max_vfreq = 0;
double desired_vfreq = 0;
double hvisible = CFG_HORIZ_VISIBLE;
double vvisible = CFG_VERT_VISIBLE;
double hfporch = CFG_HORIZ_FRONT_PORCH;
double hbporch = CFG_HORIZ_BACK_PORCH;
double hsync = CFG_HORIZ_SYNC_PULSE;
double vfporch = CFG_VERT_FRONT_PORCH;
double vbporch = CFG_VERT_BACK_PORCH;
double vsync = CFG_VERT_SYNC_PULSE;





void
banner (void)
{
      pmsg (VL_VERBOSE, "\n       +--------------------------------------------------------------+\n");
      pmsg (VL_VERBOSE, "       |                                                              |\n");
      pmsg (VL_VERBOSE, "       |     videogen %s     simple XFree86 Modeline calculator     |\n", CFG_VIDEOGEN_VERSION);
      pmsg (VL_VERBOSE, "       |                                                              |\n");
      pmsg (VL_VERBOSE, "       |              by Szabolcs Rumi, (c) 1997 - 2002               |\n");
      pmsg (VL_VERBOSE, "       |        THIS PROGRAM COMES WITH ABSOLUTELY NO WARRANTY        |\n");
      pmsg (VL_VERBOSE, "       |    for details see the GNU General Public License (GPLv2)    |\n");
      pmsg (VL_VERBOSE, "       |                                                              |\n");
      pmsg (VL_VERBOSE, "       +--------------------------------------------------------------+\n\n");
}





void
usage (void)
{
      pmsg (VL_NORMAL, "USAGE: videogen [-h] [-v|-q] [-fb|-nfb] [-nv|-nnv] [-f=<file|->] [-m=<mode>]\n");
      pmsg (VL_NORMAL, "                [-mdc=<n>] [-mhf=<n>] [-mvf=<n>] [-dvf=<n>] [-hv=<n>] [-vv=<n>]\n");
      pmsg (VL_NORMAL, "                [-hfp=<n>] [-hbp=<n>] [-hsp=<n>] [-vfp=<n>] [-vbp=<n>] [-vsp=<n>]\n\n");
}





int
main (int argc, char **argv)
{
      char pathname_buf[4096];
      arg_parse_t ap = { 0, 0, 0, NULL, &opts };
      int i;
      double calc_dc, calc_hf, calc_vf;
      unsigned int calc_hfl, calc_vfl, calc_hfp, calc_hsp, calc_hbp, calc_vfp, calc_vsp, calc_vbp;



      /*
       * reading command line parameters
       */

      ap.argc = argc;
      ap.argv = argv;

      if (arg_parse (&ap, &arg_action) < 0)
      {
            pmsg (VL_NORMAL, "command line syntax error\n");
            usage();
            exit (ERR_CMDLINE);
      }



      /*
       * reading config file
       */

      if (strcmp (cfgfile, "-"))
      {
            yyin = fopen (tpathexp (cfgfile, (char *)&pathname_buf), "r");
            if (yyin == NULL)
            {
                  pmsg (VL_NORMAL, "could not open configuration file \"%s\" (errno=%i)\n", cfgfile, errno);
            }
            else
            {
                  pmsg (VL_VERBOSE, "reading configuration from file %s\n", cfgfile);
                  if (yyparse () != 0)
                        exit (ERR_CFGFILE);
            }
      }
      else
      {
            yyin = stdin;
            if (yyin == NULL)
            {
                  pmsg (VL_DEBUG, "[main] stdin not open\n");
            }
            else
            {
                  pmsg (VL_VERBOSE, "reading configuration from standard input\n");
                  if (yyparse () != 0)
                        exit (ERR_CFGFILE);
            }
      }



      /*
       * print out some information about the program itself (in verbose mode only)
       */

      banner ();



      /*
       * check if the mandatory parameters are present
       */

      if (num_modes == 0)
      {
            pmsg (VL_NORMAL, "error: no modes (resolutions) have been specified\n");
            exit (ERR_RES);
      }

      if (max_dotclk == 0)
      {
            pmsg (VL_NORMAL, "error: the maximum dot clock rate has not been specified\n");
            exit (ERR_MDC);
      }

      if (max_hfreq == 0)
      {
            pmsg (VL_NORMAL, "error: the maximum horizontal refresh frequency has not been specified\n");
            exit (ERR_MHF);
      }

      if (max_vfreq == 0)
      {
            pmsg (VL_NORMAL, "error: the maximum vertical refresh frequency has not been specified\n");
            exit (ERR_MVF);
      }

      if (desired_vfreq == 0)
            desired_vfreq = max_vfreq;



      /*
       * do our main job
       */

      for (i = 0; i < num_modes; i++)
      {
            calc_vf = desired_vfreq;
            calc_hfl = (unsigned int)floor (modes[i].hres * 100 / hvisible / 8) * 8;

            if ((nvidia > 0) && (calc_hfl - modes[i].hres > CFG_NV_MAX_HBLANK))
            {
                  pmsg (VL_DEBUG, "[main] hblank: %u > %u\n", calc_hfl - modes[i].hres, CFG_NV_MAX_HBLANK);
                  hvisible = 100 - ((100 - hvisible) * (CFG_NV_MAX_HBLANK / (calc_hfl - modes[i].hres)));
                  calc_hfl = (unsigned int)floor (modes[i].hres * 100 / hvisible);
                  calc_hfl = (unsigned int)floor (calc_hfl / 8) * 8;
            }

            calc_hfp = (unsigned int)floor ((calc_hfl - modes[i].hres) / 64) * 8;
            calc_hbp = (unsigned int)floor ((calc_hfl - modes[i].hres - calc_hfp) / 8) * 8; 

            calc_hsp = floor (hsync * max_dotclk / 8) * 8;

            if ((nvidia > 0) && (calc_hsp > CFG_NV_MAX_HSP))
            {
                  /* calc_hsp is assumed to be a multiple of 8 because all values it is
                   * calculated from are assumed to be multiples of 8.
                   */
                  pmsg (VL_DEBUG, "[main] hsp: %u > %u\n", calc_hsp, CFG_NV_MAX_HSP);
                  calc_hsp = CFG_NV_MAX_HSP;
            }

            calc_hbp -= calc_hsp;

            calc_vfl = (unsigned int)floor (modes[i].vres * 100 / vvisible + 0.5);

            if ((nvidia > 0) && (calc_vfl - modes[i].vres > CFG_NV_MAX_VBLANK))
            {
                  pmsg (VL_DEBUG, "[main] vblank: %u > %u\n", calc_vfl - modes[i].vres, CFG_NV_MAX_VBLANK);
                  vvisible = 100 - ((100 - vvisible) * (CFG_NV_MAX_VBLANK / (calc_vfl - modes[i].vres)));
                  calc_vfl = (unsigned int)floor (modes[i].vres * 100 / vvisible);
            }

            calc_dc = calc_vf * calc_hfl * calc_vfl / 1000000;
            calc_hf = (1000 * calc_dc) / calc_hfl;

            calc_vfp = (unsigned int)vfporch;
            calc_vbp = calc_vfl - modes[i].vres - calc_vfp;

            calc_vsp = floor (vsync * calc_hf / 1000);

            if ((nvidia > 0) && (calc_vsp > CFG_NV_MAX_VSP))
            {
                  /* framelength must be the same after the correction
                   */
                  pmsg (VL_DEBUG, "[main] vsp: %u > %u\n", calc_vsp, CFG_NV_MAX_VSP);
                  calc_vsp = CFG_NV_MAX_VSP;
            }

            calc_vbp -= calc_vsp;

            pmsg (VL_DEBUG, "[main] dump 1: visible=%ux%u frame=%ux%u\n", modes[i].hres, modes[i].vres, calc_hfl, calc_vfl);
            pmsg (VL_DEBUG, "[main] dump 1: dc=%f hf=%f vf=%f\n", calc_dc, calc_hf, calc_vf);
            pmsg (VL_DEBUG, "[main] dump 1: hsp=%u vsp=%u\n\n", calc_hsp, calc_vsp);

            if (calc_dc > max_dotclk)
            {
                  pmsg (VL_DEBUG, "[main] dc: %f > %f\n", calc_dc, max_dotclk);
                  calc_dc = max_dotclk;
                  calc_vf = (1000000 * calc_dc) / (calc_hfl * calc_vfl);
            }

            calc_hf = (1000 * calc_dc) / calc_hfl;

            pmsg (VL_DEBUG, "[main] dump 2: visible=%ux%u frame=%ux%u\n", modes[i].hres, modes[i].vres, calc_hfl, calc_vfl);
            pmsg (VL_DEBUG, "[main] dump 2: dc=%f hf=%f vf=%f\n", calc_dc, calc_hf, calc_vf);
            pmsg (VL_DEBUG, "[main] dump 2: hsp=%u vsp=%u\n\n", calc_hsp, calc_vsp);

            if (calc_hf > max_hfreq)
            {
                  pmsg (VL_DEBUG, "[main] hf: %f > %f\n", calc_hf, max_hfreq);
                  calc_hf = max_hfreq;
                  calc_dc = calc_hf * calc_hfl / 1000;
                  calc_vf = (1000000 * calc_dc) / (calc_hfl * calc_vfl);
            }

            pmsg (VL_DEBUG, "[main] dump 3: visible=%ux%u frame=%ux%u\n", modes[i].hres, modes[i].vres, calc_hfl, calc_vfl);
            pmsg (VL_DEBUG, "[main] dump 3: dc=%f hf=%f vf=%f\n", calc_dc, calc_hf, calc_vf);
            pmsg (VL_DEBUG, "[main] dump 3: hsp=%u vsp=%u\n\n", calc_hsp, calc_vsp);

            /*
             * printing out the results
             */

            if (fbset == 0)
            {
                  fprintf (stdout, "Modeline \"%ux%u\" %0.2f %u %u %u %u %u %u %u %u  # %0.0f MHz, %0.1f kHz, %0.1f Hz\n",
                        modes[i].hres, modes[i].vres,
                        calc_dc,
                        modes[i].hres,
                        modes[i].hres + calc_hfp,
                        modes[i].hres + calc_hfp + calc_hsp,
                        modes[i].hres + calc_hfp + calc_hsp + calc_hbp,
                        modes[i].vres,
                        modes[i].vres + calc_vfp,
                        modes[i].vres + calc_vfp + calc_vsp,
                        modes[i].vres + calc_vfp + calc_vsp + calc_vbp,
                        calc_dc, calc_hf, calc_vf);
            }
            else
            {
                  fprintf (stdout, "timings %0.0f %u %u %u %u %u %u  # %0.0f MHz, %0.1f kHz, %0.1f Hz\n",
                        1000000 / calc_dc, calc_hbp, calc_hfp, calc_vbp, calc_vfp, calc_hsp, calc_vsp,
                        calc_dc, calc_hf, calc_vf);
            }
      }
      
      return (0);
}





/* EOF */

Generated by  Doxygen 1.6.0   Back to index