/*
* +-------------------------------------------------------+
* | |
* | 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_QUIET, "USAGE: videogen [-h] [-v|-q] [-fb|-nfb] [-nv|-nnv] [-f=<file|->] [-m=<mode>]\n");
pmsg (VL_QUIET, " [-mdc=<n>] [-mhf=<n>] [-mvf=<n>] [-dvf=<n>] [-hv=<n>] [-vv=<n>]\n");
pmsg (VL_QUIET, " [-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_VERBOSE, "command line syntax error\n");
exit (ERR_CMDLINE);
}
/*
* reading config file
*/
if (strcmp (cfgfile, "-"))
{
yyin = fopen (tpathexp (cfgfile, (char *)&pathname_buf), "r");
if (yyin == NULL)
{
pmsg (VL_VERBOSE, "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_VERBOSE, "error: no modes (resolutions) have been specified\n");
exit (ERR_RES);
}
if (max_dotclk == 0)
{
pmsg (VL_VERBOSE, "error: the maximum dot clock rate has not been specified\n");
exit (ERR_MDC);
}
if (max_hfreq == 0)
{
pmsg (VL_VERBOSE, "error: the maximum horizontal refresh frequency has not been specified\n");
exit (ERR_MHF);
}
if (max_vfreq == 0)
{
pmsg (VL_VERBOSE, "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 */
syntax highlighted by Code2HTML, v. 0.9.1