diff options
Diffstat (limited to 'board/MAI/bios_emulator/scitech/src/common/gtfcalc.c')
-rw-r--r-- | board/MAI/bios_emulator/scitech/src/common/gtfcalc.c | 436 |
1 files changed, 436 insertions, 0 deletions
diff --git a/board/MAI/bios_emulator/scitech/src/common/gtfcalc.c b/board/MAI/bios_emulator/scitech/src/common/gtfcalc.c new file mode 100644 index 00000000000..5a03ac58855 --- /dev/null +++ b/board/MAI/bios_emulator/scitech/src/common/gtfcalc.c @@ -0,0 +1,436 @@ +/**************************************************************************** +* +* 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); + rightMarginPixels = round(hPixels * c.margin) / (100 * c.cellGran); + } + else { + leftMarginPixels = 0; + rightMarginPixels = 0; + } + + /* Find the total number of active pixels in image + margins */ + hTotalActivePixels = hPixels + leftMarginPixels + rightMarginPixels; + + if (type == GTF_lockVF) { + /* Find the ideal blanking duty cycle */ + idealDutyCycle = c.c - ((c.m * hPeriod) / 1000); + } + else if (type == GTF_lockHF) { + /* Find the ideal blanking duty cycle */ + idealDutyCycle = c.c - (c.m / hFreq); + } + else if (type == GTF_lockPF) { + /* Find ideal horizontal period from blanking duty cycle formula */ + idealHPeriod = (((c.c - 100) + (sqrt((pow(100-c.c,2)) + + (0.4 * c.m * (hTotalActivePixels + rightMarginPixels + + leftMarginPixels) / dotClock)))) / (2 * c.m)) * 1000; + + /* Find the ideal blanking duty cycle */ + idealDutyCycle = c.c - ((c.m * idealHPeriod) / 1000); + } + + /* Find the number of pixels in blanking time */ + hBlankPixels = round((hTotalActivePixels * idealDutyCycle) / + ((100 - idealDutyCycle) * c.cellGran)) * c.cellGran; + + /* Find the total number of pixels */ + hTotalPixels = hTotalActivePixels + hBlankPixels; + + /* Find the horizontal back porch */ + hBackPorch = round((hBlankPixels / 2) / c.cellGran) * c.cellGran; + + /* Find the horizontal sync width */ + hSyncWidth = round(((c.hSync/100) * hTotalPixels) / c.cellGran) * c.cellGran; + + /* Find the horizontal sync + back porch */ + hSyncBP = hBackPorch + hSyncWidth; + + if (type == GTF_lockPF) { + /* Find the horizontal frequency */ + hFreq = (dotClock / hTotalPixels) * 1000; + + /* 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; + + /* Find the actual vertical field frequency */ + vFieldRate = (hFreq / vTotalLines) * 1000; + } + else { + if (type == GTF_lockVF) { + /* Find the horizontal frequency */ + hFreq = 1000 / hPeriod; + } + else if (type == GTF_lockHF) { + /* Find the horizontal frequency */ + hPeriod = 1000 / hFreq; + } + + /* Find the pixel clock frequency */ + dotClock = hTotalPixels / hPeriod; + } + + /* Return the computed frequencies */ + t->vFreq = vFieldRate; + t->hFreq = hFreq; + t->dotClock = dotClock; + + /* Determine the vertical timing parameters */ + t->h.hTotal = (int)hTotalPixels; + t->h.hDisp = (int)hTotalActivePixels; + t->h.hSyncStart = t->h.hTotal - (int)hSyncBP; + t->h.hSyncEnd = t->h.hTotal - (int)hBackPorch; + t->h.hFrontPorch = t->h.hSyncStart - t->h.hDisp; + t->h.hSyncWidth = (int)hSyncWidth; + t->h.hBackPorch = (int)hBackPorch; + + /* Determine the vertical timing parameters */ + t->v.vTotal = (int)vTotalLines; + t->v.vDisp = (int)vLines; + t->v.vSyncStart = t->v.vTotal - (int)vSyncBP; + t->v.vSyncEnd = t->v.vTotal - (int)vBackPorch; + t->v.vFrontPorch = t->v.vSyncStart - t->v.vDisp; + t->v.vSyncWidth = (int)c.vSyncRqd; + t->v.vBackPorch = (int)vBackPorch; + if (wantInterlace) { + /* Halve the timings for interlaced modes */ + t->v.vTotal /= 2; + t->v.vDisp /= 2; + t->v.vSyncStart /= 2; + t->v.vSyncEnd /= 2; + t->v.vFrontPorch /= 2; + t->v.vSyncWidth /= 2; + t->v.vBackPorch /= 2; + t->dotClock /= 2; + } + + /* Mark as GTF timing using the sync polarities */ + t->interlace = (wantInterlace) ? 'I' : 'N'; + t->hSyncPol = '-'; + t->vSyncPol = '+'; +} + +void GTF_getConstants(GTF_constants *constants) +{ *constants = GC; } + +void GTF_setConstants(GTF_constants *constants) +{ GC = *constants; } + +#ifdef TESTING_GTF + +void main(int argc,char *argv[]) +{ + FILE *f; + double xPixels,yPixels,freq; + ibool interlace; + GTF_timings t; + + if (argc != 5 && argc != 6) { + printf("Usage: GTFCALC <xPixels> <yPixels> <freq> [[Hz] [KHz] [MHz]] [I]\n"); + printf("\n"); + printf("where <xPixels> is the horizontal resolution of the mode, <yPixels> is the\n"); + printf("vertical resolution of the mode. The <freq> value will be the frequency to\n"); + printf("drive the calculations, and will be either the vertical frequency (in Hz)\n"); + printf("the horizontal frequency (in KHz) or the dot clock (in MHz). To generate\n"); + printf("timings for an interlaced mode, add 'I' to the end of the command line.\n"); + printf("\n"); + printf("For example to generate timings for 640x480 at 60Hz vertical:\n"); + printf("\n"); + printf(" GTFCALC 640 480 60 Hz\n"); + printf("\n"); + printf("For example to generate timings for 640x480 at 31.5KHz horizontal:\n"); + printf("\n"); + printf(" GTFCALC 640 480 31.5 KHz\n"); + printf("\n"); + printf("For example to generate timings for 640x480 with a 25.175Mhz dot clock:\n"); + printf("\n"); + printf(" GTFCALC 640 480 25.175 MHz\n"); + printf("\n"); + printf("GTFCALC will print a summary of the results found, and dump the CRTC\n"); + printf("values to the UVCONFIG.CRT file in the format used by SciTech Display Doctor.\n"); + exit(1); + } + + /* Get values from command line */ + xPixels = atof(argv[1]); + yPixels = atof(argv[2]); + freq = atof(argv[3]); + interlace = ((argc == 6) && (argv[5][0] == 'I')); + + /* Compute the CRTC timings */ + if (toupper(argv[4][0]) == 'H') + GTF_calcTimings(xPixels,yPixels,freq,GTF_lockVF,false,interlace,&t); + else if (toupper(argv[4][0]) == 'K') + GTF_calcTimings(xPixels,yPixels,freq,GTF_lockHF,false,interlace,&t); + else if (toupper(argv[4][0]) == 'M') + GTF_calcTimings(xPixels,yPixels,freq,GTF_lockPF,false,interlace,&t); + else { + printf("Unknown command line!\n"); + exit(1); + } + + /* Dump summary info to standard output */ + printf("CRTC values for %.0fx%.0f @ %.2f %s\n", xPixels, yPixels, freq, argv[4]); + printf("\n"); + printf(" hTotal = %-4d vTotal = %-4d\n", + t.h.hTotal, t.v.vTotal); + printf(" hDisp = %-4d vDisp = %-4d\n", + t.h.hDisp, t.v.vDisp); + printf(" hSyncStart = %-4d vSyncStart = %-4d\n", + t.h.hSyncStart, t.v.vSyncStart); + printf(" hSyncEnd = %-4d vSyncEnd = %-4d\n", + t.h.hSyncEnd, t.v.vSyncEnd); + printf(" hFrontPorch = %-4d vFrontPorch = %-4d\n", + t.h.hFrontPorch, t.v.vFrontPorch); + printf(" hSyncWidth = %-4d vSyncWidth = %-4d\n", + t.h.hSyncWidth, t.v.vSyncWidth); + printf(" hBackPorch = %-4d vBackPorch = %-4d\n", + t.h.hBackPorch, t.v.vBackPorch); + printf("\n"); + printf(" Interlaced = %s\n", (t.interlace == 'I') ? "Yes" : "No"); + printf(" H sync pol = %c\n", t.hSyncPol); + printf(" V sync pol = %c\n", t.vSyncPol); + printf("\n"); + printf(" Vert freq = %.2f Hz\n", t.vFreq); + printf(" Horiz freq = %.2f KHz\n", t.hFreq); + printf(" Dot Clock = %.2f Mhz\n", t.dotClock); + + /* Dump to file in format used by SciTech Display Doctor */ + if ((f = fopen("UVCONFIG.CRT","w")) != NULL) { + fprintf(f, "[%.0f %.0f]\n", xPixels, yPixels); + fprintf(f, "%d %d %d %d '%c' %s\n", + t.h.hTotal, t.h.hDisp, + t.h.hSyncStart, t.h.hSyncEnd, + t.hSyncPol, (t.interlace == 'I') ? "I" : "NI"); + fprintf(f, "%d %d %d %d '%c'\n", + t.v.vTotal, t.v.vDisp, + t.v.vSyncStart, t.v.vSyncEnd, + t.vSyncPol); + fprintf(f, "%.2f\n", t.dotClock); + fclose(f); + } +} + +#endif /* TESTING */ |