]>
git.ipfire.org Git - people/ms/u-boot.git/blob - board/MAI/bios_emulator/scitech/src/common/gtfcalc.c
1 /****************************************************************************
3 * VESA Generalized Timing Formula (GTF)
6 * ========================================================================
8 * The contents of this file are subject to the SciTech MGL Public
9 * License Version 1.0 (the "License"); you may not use this file
10 * except in compliance with the License. You may obtain a copy of
11 * the License at http://www.scitechsoft.com/mgl-license.txt
13 * Software distributed under the License is distributed on an
14 * "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
15 * implied. See the License for the specific language governing
16 * rights and limitations under the License.
18 * The Original Code is Copyright (C) 1991-1998 SciTech Software, Inc.
20 * The Initial Developer of the Original Code is SciTech Software, Inc.
21 * All Rights Reserved.
23 * ========================================================================
25 * Developed by: SciTech Software, Inc.
30 * Description: C module for generating GTF compatible timings given a set
31 * of input requirements. Translated from the original GTF
32 * 1.14 spreadsheet definition.
34 * Compile with #define TESTING to build a command line test
37 * NOTE: The code in here has been written for clarity and
38 * to follow the original GTF spec as closely as
41 ****************************************************************************/
52 /*------------------------- Global Variables ------------------------------*/
54 static GTF_constants GC
= {
55 1.8, /* Margin size as percentage of display */
56 8, /* Character cell granularity */
57 1, /* Minimum front porch in lines/chars */
58 3, /* Width of V sync in lines */
59 8, /* Width of H sync as percent of total */
60 550, /* Minimum vertical sync + back porch (us) */
61 600, /* Blanking formula gradient */
62 40, /* Blanking formula offset */
63 128, /* Blanking formula scaling factor */
64 20, /* Blanking formula scaling factor weight */
67 /*-------------------------- Implementation -------------------------------*/
70 /* These functions are not supported in a VxD, so we stub them out so this
71 * module will at least compile. Calling the functions in here will do
77 double floor(double x
)
80 double pow(double x
,double y
)
84 static double round(double v
)
86 return floor(v
+ 0.5);
89 static void GetInternalConstants(GTF_constants
*c
)
90 /****************************************************************************
92 * Function: GetInternalConstants
93 * Parameters: c - Place to store the internal constants
95 * Description: Calculates the rounded, internal set of GTF constants.
96 * These constants are different to the real GTF constants
97 * that can be set up for the monitor. The calculations to
98 * get these real constants are defined in the 'Work Area'
99 * after the constants are defined in the Excel spreadsheet.
101 ****************************************************************************/
103 c
->margin
= GC
.margin
;
104 c
->cellGran
= round(GC
.cellGran
);
105 c
->minPorch
= round(GC
.minPorch
);
106 c
->vSyncRqd
= round(GC
.vSyncRqd
);
108 c
->minVSyncBP
= GC
.minVSyncBP
;
113 c
->m
= (c
->k
/ 256) * GC
.m
;
114 c
->c
= (GC
.c
- GC
.j
) * (c
->k
/ 256) + GC
.j
;
118 void GTF_calcTimings(double hPixels
,double vLines
,double freq
,
119 int type
,ibool wantMargins
,ibool wantInterlace
,GTF_timings
*t
)
120 /****************************************************************************
122 * Function: GTF_calcTimings
123 * Parameters: hPixels - X resolution
124 * vLines - Y resolution
125 * freq - Frequency (Hz, KHz or MHz depending on type)
126 * type - 1 - vertical, 2 - horizontal, 3 - dot clock
127 * margins - True if margins should be generated
128 * interlace - True if interlaced timings to be generated
129 * t - Place to store the resulting timings
131 * Description: Calculates a set of GTF timing parameters given a specified
132 * resolution and vertical frequency. The horizontal frequency
133 * and dot clock will be automatically generated by this
136 * For interlaced modes the CRTC parameters are calculated for
137 * a single field, so will be half what would be used in
138 * a non-interlaced mode.
140 ****************************************************************************/
142 double interlace
,vFieldRate
,hPeriod
;
143 double topMarginLines
,botMarginLines
;
144 double leftMarginPixels
,rightMarginPixels
;
145 double hPeriodEst
,vSyncBP
,vBackPorch
;
146 double vTotalLines
,vFieldRateEst
;
147 double hTotalPixels
,hTotalActivePixels
,hBlankPixels
;
148 double idealDutyCycle
,hSyncWidth
,hSyncBP
,hBackPorch
;
150 double vFreq
,hFreq
,dotClock
;
153 /* Get rounded GTF constants used for internal calculations */
154 GetInternalConstants(&c
);
156 /* Move input parameters into appropriate variables */
157 vFreq
= hFreq
= dotClock
= freq
;
159 /* Round pixels to character cell granularity */
160 hPixels
= round(hPixels
/ c
.cellGran
) * c
.cellGran
;
162 /* For interlaced mode halve the vertical parameters, and double
163 * the required field refresh rate.
170 /* Determine the lines for margins */
172 topMarginLines
= round(c
.margin
/ 100 * vLines
);
173 botMarginLines
= round(c
.margin
/ 100 * vLines
);
180 if (type
!= GTF_lockPF
) {
181 if (type
== GTF_lockVF
) {
182 /* Estimate the horizontal period */
183 hPeriodEst
= ((1/vFieldRate
) - (c
.minVSyncBP
/1000000)) /
184 (vLines
+ (2*topMarginLines
) + c
.minPorch
+ interlace
) * 1000000;
186 /* Find the number of lines in vSync + back porch */
187 vSyncBP
= round(c
.minVSyncBP
/ hPeriodEst
);
189 else if (type
== GTF_lockHF
) {
190 /* Find the number of lines in vSync + back porch */
191 vSyncBP
= round((c
.minVSyncBP
* hFreq
) / 1000);
194 /* Find the number of lines in the V back porch alone */
195 vBackPorch
= vSyncBP
- c
.vSyncRqd
;
197 /* Find the total number of lines in the vertical period */
198 vTotalLines
= vLines
+ topMarginLines
+ botMarginLines
+ vSyncBP
199 + interlace
+ c
.minPorch
;
201 if (type
== GTF_lockVF
) {
202 /* Estimate the vertical frequency */
203 vFieldRateEst
= 1000000 / (hPeriodEst
* vTotalLines
);
205 /* Find the actual horizontal period */
206 hPeriod
= (hPeriodEst
* vFieldRateEst
) / vFieldRate
;
208 /* Find the actual vertical field frequency */
209 vFieldRate
= 1000000 / (hPeriod
* vTotalLines
);
211 else if (type
== GTF_lockHF
) {
212 /* Find the actual vertical field frequency */
213 vFieldRate
= (hFreq
/ vTotalLines
) * 1000;
217 /* Find the number of pixels in the left and right margins */
219 leftMarginPixels
= round(hPixels
* c
.margin
) / (100 * c
.cellGran
);
220 rightMarginPixels
= round(hPixels
* c
.margin
) / (100 * c
.cellGran
);
223 leftMarginPixels
= 0;
224 rightMarginPixels
= 0;
227 /* Find the total number of active pixels in image + margins */
228 hTotalActivePixels
= hPixels
+ leftMarginPixels
+ rightMarginPixels
;
230 if (type
== GTF_lockVF
) {
231 /* Find the ideal blanking duty cycle */
232 idealDutyCycle
= c
.c
- ((c
.m
* hPeriod
) / 1000);
234 else if (type
== GTF_lockHF
) {
235 /* Find the ideal blanking duty cycle */
236 idealDutyCycle
= c
.c
- (c
.m
/ hFreq
);
238 else if (type
== GTF_lockPF
) {
239 /* Find ideal horizontal period from blanking duty cycle formula */
240 idealHPeriod
= (((c
.c
- 100) + (sqrt((pow(100-c
.c
,2)) +
241 (0.4 * c
.m
* (hTotalActivePixels
+ rightMarginPixels
+
242 leftMarginPixels
) / dotClock
)))) / (2 * c
.m
)) * 1000;
244 /* Find the ideal blanking duty cycle */
245 idealDutyCycle
= c
.c
- ((c
.m
* idealHPeriod
) / 1000);
248 /* Find the number of pixels in blanking time */
249 hBlankPixels
= round((hTotalActivePixels
* idealDutyCycle
) /
250 ((100 - idealDutyCycle
) * c
.cellGran
)) * c
.cellGran
;
252 /* Find the total number of pixels */
253 hTotalPixels
= hTotalActivePixels
+ hBlankPixels
;
255 /* Find the horizontal back porch */
256 hBackPorch
= round((hBlankPixels
/ 2) / c
.cellGran
) * c
.cellGran
;
258 /* Find the horizontal sync width */
259 hSyncWidth
= round(((c
.hSync
/100) * hTotalPixels
) / c
.cellGran
) * c
.cellGran
;
261 /* Find the horizontal sync + back porch */
262 hSyncBP
= hBackPorch
+ hSyncWidth
;
264 if (type
== GTF_lockPF
) {
265 /* Find the horizontal frequency */
266 hFreq
= (dotClock
/ hTotalPixels
) * 1000;
268 /* Find the number of lines in vSync + back porch */
269 vSyncBP
= round((c
.minVSyncBP
* hFreq
) / 1000);
271 /* Find the number of lines in the V back porch alone */
272 vBackPorch
= vSyncBP
- c
.vSyncRqd
;
274 /* Find the total number of lines in the vertical period */
275 vTotalLines
= vLines
+ topMarginLines
+ botMarginLines
+ vSyncBP
276 + interlace
+ c
.minPorch
;
278 /* Find the actual vertical field frequency */
279 vFieldRate
= (hFreq
/ vTotalLines
) * 1000;
282 if (type
== GTF_lockVF
) {
283 /* Find the horizontal frequency */
284 hFreq
= 1000 / hPeriod
;
286 else if (type
== GTF_lockHF
) {
287 /* Find the horizontal frequency */
288 hPeriod
= 1000 / hFreq
;
291 /* Find the pixel clock frequency */
292 dotClock
= hTotalPixels
/ hPeriod
;
295 /* Return the computed frequencies */
296 t
->vFreq
= vFieldRate
;
298 t
->dotClock
= dotClock
;
300 /* Determine the vertical timing parameters */
301 t
->h
.hTotal
= (int)hTotalPixels
;
302 t
->h
.hDisp
= (int)hTotalActivePixels
;
303 t
->h
.hSyncStart
= t
->h
.hTotal
- (int)hSyncBP
;
304 t
->h
.hSyncEnd
= t
->h
.hTotal
- (int)hBackPorch
;
305 t
->h
.hFrontPorch
= t
->h
.hSyncStart
- t
->h
.hDisp
;
306 t
->h
.hSyncWidth
= (int)hSyncWidth
;
307 t
->h
.hBackPorch
= (int)hBackPorch
;
309 /* Determine the vertical timing parameters */
310 t
->v
.vTotal
= (int)vTotalLines
;
311 t
->v
.vDisp
= (int)vLines
;
312 t
->v
.vSyncStart
= t
->v
.vTotal
- (int)vSyncBP
;
313 t
->v
.vSyncEnd
= t
->v
.vTotal
- (int)vBackPorch
;
314 t
->v
.vFrontPorch
= t
->v
.vSyncStart
- t
->v
.vDisp
;
315 t
->v
.vSyncWidth
= (int)c
.vSyncRqd
;
316 t
->v
.vBackPorch
= (int)vBackPorch
;
318 /* Halve the timings for interlaced modes */
321 t
->v
.vSyncStart
/= 2;
323 t
->v
.vFrontPorch
/= 2;
324 t
->v
.vSyncWidth
/= 2;
325 t
->v
.vBackPorch
/= 2;
329 /* Mark as GTF timing using the sync polarities */
330 t
->interlace
= (wantInterlace
) ? 'I' : 'N';
335 void GTF_getConstants(GTF_constants
*constants
)
338 void GTF_setConstants(GTF_constants
*constants
)
343 void main(int argc
,char *argv
[])
346 double xPixels
,yPixels
,freq
;
350 if (argc
!= 5 && argc
!= 6) {
351 printf("Usage: GTFCALC <xPixels> <yPixels> <freq> [[Hz] [KHz] [MHz]] [I]\n");
353 printf("where <xPixels> is the horizontal resolution of the mode, <yPixels> is the\n");
354 printf("vertical resolution of the mode. The <freq> value will be the frequency to\n");
355 printf("drive the calculations, and will be either the vertical frequency (in Hz)\n");
356 printf("the horizontal frequency (in KHz) or the dot clock (in MHz). To generate\n");
357 printf("timings for an interlaced mode, add 'I' to the end of the command line.\n");
359 printf("For example to generate timings for 640x480 at 60Hz vertical:\n");
361 printf(" GTFCALC 640 480 60 Hz\n");
363 printf("For example to generate timings for 640x480 at 31.5KHz horizontal:\n");
365 printf(" GTFCALC 640 480 31.5 KHz\n");
367 printf("For example to generate timings for 640x480 with a 25.175Mhz dot clock:\n");
369 printf(" GTFCALC 640 480 25.175 MHz\n");
371 printf("GTFCALC will print a summary of the results found, and dump the CRTC\n");
372 printf("values to the UVCONFIG.CRT file in the format used by SciTech Display Doctor.\n");
376 /* Get values from command line */
377 xPixels
= atof(argv
[1]);
378 yPixels
= atof(argv
[2]);
379 freq
= atof(argv
[3]);
380 interlace
= ((argc
== 6) && (argv
[5][0] == 'I'));
382 /* Compute the CRTC timings */
383 if (toupper(argv
[4][0]) == 'H')
384 GTF_calcTimings(xPixels
,yPixels
,freq
,GTF_lockVF
,false,interlace
,&t
);
385 else if (toupper(argv
[4][0]) == 'K')
386 GTF_calcTimings(xPixels
,yPixels
,freq
,GTF_lockHF
,false,interlace
,&t
);
387 else if (toupper(argv
[4][0]) == 'M')
388 GTF_calcTimings(xPixels
,yPixels
,freq
,GTF_lockPF
,false,interlace
,&t
);
390 printf("Unknown command line!\n");
394 /* Dump summary info to standard output */
395 printf("CRTC values for %.0fx%.0f @ %.2f %s\n", xPixels
, yPixels
, freq
, argv
[4]);
397 printf(" hTotal = %-4d vTotal = %-4d\n",
398 t
.h
.hTotal
, t
.v
.vTotal
);
399 printf(" hDisp = %-4d vDisp = %-4d\n",
400 t
.h
.hDisp
, t
.v
.vDisp
);
401 printf(" hSyncStart = %-4d vSyncStart = %-4d\n",
402 t
.h
.hSyncStart
, t
.v
.vSyncStart
);
403 printf(" hSyncEnd = %-4d vSyncEnd = %-4d\n",
404 t
.h
.hSyncEnd
, t
.v
.vSyncEnd
);
405 printf(" hFrontPorch = %-4d vFrontPorch = %-4d\n",
406 t
.h
.hFrontPorch
, t
.v
.vFrontPorch
);
407 printf(" hSyncWidth = %-4d vSyncWidth = %-4d\n",
408 t
.h
.hSyncWidth
, t
.v
.vSyncWidth
);
409 printf(" hBackPorch = %-4d vBackPorch = %-4d\n",
410 t
.h
.hBackPorch
, t
.v
.vBackPorch
);
412 printf(" Interlaced = %s\n", (t
.interlace
== 'I') ? "Yes" : "No");
413 printf(" H sync pol = %c\n", t
.hSyncPol
);
414 printf(" V sync pol = %c\n", t
.vSyncPol
);
416 printf(" Vert freq = %.2f Hz\n", t
.vFreq
);
417 printf(" Horiz freq = %.2f KHz\n", t
.hFreq
);
418 printf(" Dot Clock = %.2f Mhz\n", t
.dotClock
);
420 /* Dump to file in format used by SciTech Display Doctor */
421 if ((f
= fopen("UVCONFIG.CRT","w")) != NULL
) {
422 fprintf(f
, "[%.0f %.0f]\n", xPixels
, yPixels
);
423 fprintf(f
, "%d %d %d %d '%c' %s\n",
424 t
.h
.hTotal
, t
.h
.hDisp
,
425 t
.h
.hSyncStart
, t
.h
.hSyncEnd
,
426 t
.hSyncPol
, (t
.interlace
== 'I') ? "I" : "NI");
427 fprintf(f
, "%d %d %d %d '%c'\n",
428 t
.v
.vTotal
, t
.v
.vDisp
,
429 t
.v
.vSyncStart
, t
.v
.vSyncEnd
,
431 fprintf(f
, "%.2f\n", t
.dotClock
);