gtfcalc.c

来自「适合KS8695X」· C语言 代码 · 共 437 行 · 第 1/2 页

C
437
字号
/****************************************************************************
*
*                   VESA Generalized Timing Formula (GTF)
*                               Version 1.1
*
*  ========================================================================
*
*    The contents of this file are subject to the SciTech MGL Public
*    License Version 1.0 (the "License"); you may not use this file
*    except in compliance with the License. You may obtain a copy of
*    the License at http://www.scitechsoft.com/mgl-license.txt
*
*    Software distributed under the License is distributed on an
*    "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
*    implied. See the License for the specific language governing
*    rights and limitations under the License.
*
*    The Original Code is Copyright (C) 1991-1998 SciTech Software, Inc.
*
*    The Initial Developer of the Original Code is SciTech Software, Inc.
*    All Rights Reserved.
*
*  ========================================================================
*
* Developed by: SciTech Software, Inc.
*
* Language:     ANSI C
* Environment:  Any.
*
* Description:  C module for generating GTF compatible timings given a set
*               of input requirements. Translated from the original GTF
*               1.14 spreadsheet definition.
*
*               Compile with #define TESTING to build a command line test
*               program.
*
*               NOTE: The code in here has been written for clarity and
*                     to follow the original GTF spec as closely as
*                     possible.
*
****************************************************************************/

#include "gtf.h"
#ifndef __WIN32_VXD__
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#include <math.h>
#endif

/*------------------------- Global Variables ------------------------------*/

static GTF_constants GC = {
    1.8,                    /* Margin size as percentage of display     */
    8,                      /* Character cell granularity               */
    1,                      /* Minimum front porch in lines/chars       */
    3,                      /* Width of V sync in lines                 */
    8,                      /* Width of H sync as percent of total      */
    550,                    /* Minimum vertical sync + back porch (us)  */
    600,                    /* Blanking formula gradient                */
    40,                     /* Blanking formula offset                  */
    128,                    /* Blanking formula scaling factor          */
    20,                     /* Blanking formula scaling factor weight   */
    };

/*-------------------------- Implementation -------------------------------*/

#ifdef __WIN32_VXD__
/* These functions are not supported in a VxD, so we stub them out so this
 * module will at least compile. Calling the functions in here will do
 * something wierd!
 */
double sqrt(double x)
{ return x; }

double floor(double x)
{ return x; }

double pow(double x,double y)
{ return x*y; }
#endif

static double round(double v)
{
    return floor(v + 0.5);
}

static void GetInternalConstants(GTF_constants *c)
/****************************************************************************
*
* Function:     GetInternalConstants
* Parameters:   c   - Place to store the internal constants
*
* Description:  Calculates the rounded, internal set of GTF constants.
*               These constants are different to the real GTF constants
*               that can be set up for the monitor. The calculations to
*               get these real constants are defined in the 'Work Area'
*               after the constants are defined in the Excel spreadsheet.
*
****************************************************************************/
{
    c->margin = GC.margin;
    c->cellGran = round(GC.cellGran);
    c->minPorch = round(GC.minPorch);
    c->vSyncRqd = round(GC.vSyncRqd);
    c->hSync = GC.hSync;
    c->minVSyncBP = GC.minVSyncBP;
    if (GC.k == 0)
	c->k = 0.001;
    else
	c->k = GC.k;
    c->m = (c->k / 256) * GC.m;
    c->c = (GC.c - GC.j) * (c->k / 256) + GC.j;
    c->j = GC.j;
}

void GTF_calcTimings(double hPixels,double vLines,double freq,
    int type,ibool wantMargins,ibool wantInterlace,GTF_timings *t)
/****************************************************************************
*
* Function:     GTF_calcTimings
* Parameters:   hPixels     - X resolution
*               vLines      - Y resolution
*               freq        - Frequency (Hz, KHz or MHz depending on type)
*               type        - 1 - vertical, 2 - horizontal, 3 - dot clock
*               margins     - True if margins should be generated
*               interlace   - True if interlaced timings to be generated
*               t           - Place to store the resulting timings
*
* Description:  Calculates a set of GTF timing parameters given a specified
*               resolution and vertical frequency. The horizontal frequency
*               and dot clock will be automatically generated by this
*               routines.
*
*               For interlaced modes the CRTC parameters are calculated for
*               a single field, so will be half what would be used in
*               a non-interlaced mode.
*
****************************************************************************/
{
    double          interlace,vFieldRate,hPeriod;
    double          topMarginLines,botMarginLines;
    double          leftMarginPixels,rightMarginPixels;
    double          hPeriodEst,vSyncBP,vBackPorch;
    double          vTotalLines,vFieldRateEst;
    double          hTotalPixels,hTotalActivePixels,hBlankPixels;
    double          idealDutyCycle,hSyncWidth,hSyncBP,hBackPorch;
    double          idealHPeriod;
    double          vFreq,hFreq,dotClock;
    GTF_constants   c;

    /* Get rounded GTF constants used for internal calculations */
    GetInternalConstants(&c);

    /* Move input parameters into appropriate variables */
    vFreq = hFreq = dotClock = freq;

    /* Round pixels to character cell granularity */
    hPixels = round(hPixels / c.cellGran) * c.cellGran;

    /* For interlaced mode halve the vertical parameters, and double
     * the required field refresh rate.
     */
    vFieldRate = vFreq;
    interlace = 0;
    if (wantInterlace)
	dotClock *= 2;

    /* Determine the lines for margins */
    if (wantMargins) {
	topMarginLines = round(c.margin / 100 * vLines);
	botMarginLines = round(c.margin / 100 * vLines);
	}
    else {
	topMarginLines = 0;
	botMarginLines = 0;
	}

    if (type != GTF_lockPF) {
	if (type == GTF_lockVF) {
	    /* Estimate the horizontal period */
	    hPeriodEst = ((1/vFieldRate) - (c.minVSyncBP/1000000)) /
		(vLines + (2*topMarginLines) + c.minPorch + interlace) * 1000000;

	    /* Find the number of lines in vSync + back porch */
	    vSyncBP = round(c.minVSyncBP / hPeriodEst);
	    }
	else if (type == GTF_lockHF) {
	    /* Find the number of lines in vSync + back porch */
	    vSyncBP = round((c.minVSyncBP * hFreq) / 1000);
	    }

	/* Find the number of lines in the V back porch alone */
	vBackPorch = vSyncBP - c.vSyncRqd;

	/* Find the total number of lines in the vertical period */
	vTotalLines = vLines + topMarginLines + botMarginLines + vSyncBP
	    + interlace + c.minPorch;

	if (type == GTF_lockVF) {
	    /* Estimate the vertical frequency */
	    vFieldRateEst = 1000000 / (hPeriodEst * vTotalLines);

	    /* Find the actual horizontal period */
	    hPeriod = (hPeriodEst * vFieldRateEst) / vFieldRate;

	    /* Find the actual vertical field frequency */
	    vFieldRate = 1000000 / (hPeriod * vTotalLines);
	    }
	else if (type == GTF_lockHF) {
	    /* Find the actual vertical field frequency */
	    vFieldRate = (hFreq / vTotalLines) * 1000;
	    }
	}

    /* Find the number of pixels in the left and right margins */
    if (wantMargins) {
	leftMarginPixels = round(hPixels * c.margin) / (100 * c.cellGran);

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?