]> git.ipfire.org Git - people/ms/u-boot.git/blob - board/MAI/bios_emulator/scitech/src/common/gtfcalc.c
* Code cleanup:
[people/ms/u-boot.git] / board / MAI / bios_emulator / scitech / src / common / gtfcalc.c
1 /****************************************************************************
2 *
3 * VESA Generalized Timing Formula (GTF)
4 * Version 1.1
5 *
6 * ========================================================================
7 *
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
12 *
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.
17 *
18 * The Original Code is Copyright (C) 1991-1998 SciTech Software, Inc.
19 *
20 * The Initial Developer of the Original Code is SciTech Software, Inc.
21 * All Rights Reserved.
22 *
23 * ========================================================================
24 *
25 * Developed by: SciTech Software, Inc.
26 *
27 * Language: ANSI C
28 * Environment: Any.
29 *
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.
33 *
34 * Compile with #define TESTING to build a command line test
35 * program.
36 *
37 * NOTE: The code in here has been written for clarity and
38 * to follow the original GTF spec as closely as
39 * possible.
40 *
41 ****************************************************************************/
42
43 #include "gtf.h"
44 #ifndef __WIN32_VXD__
45 #include <stdio.h>
46 #include <stdlib.h>
47 #include <string.h>
48 #include <ctype.h>
49 #include <math.h>
50 #endif
51
52 /*------------------------- Global Variables ------------------------------*/
53
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 */
65 };
66
67 /*-------------------------- Implementation -------------------------------*/
68
69 #ifdef __WIN32_VXD__
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
72 * something wierd!
73 */
74 double sqrt(double x)
75 { return x; }
76
77 double floor(double x)
78 { return x; }
79
80 double pow(double x,double y)
81 { return x*y; }
82 #endif
83
84 static double round(double v)
85 {
86 return floor(v + 0.5);
87 }
88
89 static void GetInternalConstants(GTF_constants *c)
90 /****************************************************************************
91 *
92 * Function: GetInternalConstants
93 * Parameters: c - Place to store the internal constants
94 *
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.
100 *
101 ****************************************************************************/
102 {
103 c->margin = GC.margin;
104 c->cellGran = round(GC.cellGran);
105 c->minPorch = round(GC.minPorch);
106 c->vSyncRqd = round(GC.vSyncRqd);
107 c->hSync = GC.hSync;
108 c->minVSyncBP = GC.minVSyncBP;
109 if (GC.k == 0)
110 c->k = 0.001;
111 else
112 c->k = GC.k;
113 c->m = (c->k / 256) * GC.m;
114 c->c = (GC.c - GC.j) * (c->k / 256) + GC.j;
115 c->j = GC.j;
116 }
117
118 void GTF_calcTimings(double hPixels,double vLines,double freq,
119 int type,ibool wantMargins,ibool wantInterlace,GTF_timings *t)
120 /****************************************************************************
121 *
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
130 *
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
134 * routines.
135 *
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.
139 *
140 ****************************************************************************/
141 {
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;
149 double idealHPeriod;
150 double vFreq,hFreq,dotClock;
151 GTF_constants c;
152
153 /* Get rounded GTF constants used for internal calculations */
154 GetInternalConstants(&c);
155
156 /* Move input parameters into appropriate variables */
157 vFreq = hFreq = dotClock = freq;
158
159 /* Round pixels to character cell granularity */
160 hPixels = round(hPixels / c.cellGran) * c.cellGran;
161
162 /* For interlaced mode halve the vertical parameters, and double
163 * the required field refresh rate.
164 */
165 vFieldRate = vFreq;
166 interlace = 0;
167 if (wantInterlace)
168 dotClock *= 2;
169
170 /* Determine the lines for margins */
171 if (wantMargins) {
172 topMarginLines = round(c.margin / 100 * vLines);
173 botMarginLines = round(c.margin / 100 * vLines);
174 }
175 else {
176 topMarginLines = 0;
177 botMarginLines = 0;
178 }
179
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;
185
186 /* Find the number of lines in vSync + back porch */
187 vSyncBP = round(c.minVSyncBP / hPeriodEst);
188 }
189 else if (type == GTF_lockHF) {
190 /* Find the number of lines in vSync + back porch */
191 vSyncBP = round((c.minVSyncBP * hFreq) / 1000);
192 }
193
194 /* Find the number of lines in the V back porch alone */
195 vBackPorch = vSyncBP - c.vSyncRqd;
196
197 /* Find the total number of lines in the vertical period */
198 vTotalLines = vLines + topMarginLines + botMarginLines + vSyncBP
199 + interlace + c.minPorch;
200
201 if (type == GTF_lockVF) {
202 /* Estimate the vertical frequency */
203 vFieldRateEst = 1000000 / (hPeriodEst * vTotalLines);
204
205 /* Find the actual horizontal period */
206 hPeriod = (hPeriodEst * vFieldRateEst) / vFieldRate;
207
208 /* Find the actual vertical field frequency */
209 vFieldRate = 1000000 / (hPeriod * vTotalLines);
210 }
211 else if (type == GTF_lockHF) {
212 /* Find the actual vertical field frequency */
213 vFieldRate = (hFreq / vTotalLines) * 1000;
214 }
215 }
216
217 /* Find the number of pixels in the left and right margins */
218 if (wantMargins) {
219 leftMarginPixels = round(hPixels * c.margin) / (100 * c.cellGran);
220 rightMarginPixels = round(hPixels * c.margin) / (100 * c.cellGran);
221 }
222 else {
223 leftMarginPixels = 0;
224 rightMarginPixels = 0;
225 }
226
227 /* Find the total number of active pixels in image + margins */
228 hTotalActivePixels = hPixels + leftMarginPixels + rightMarginPixels;
229
230 if (type == GTF_lockVF) {
231 /* Find the ideal blanking duty cycle */
232 idealDutyCycle = c.c - ((c.m * hPeriod) / 1000);
233 }
234 else if (type == GTF_lockHF) {
235 /* Find the ideal blanking duty cycle */
236 idealDutyCycle = c.c - (c.m / hFreq);
237 }
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;
243
244 /* Find the ideal blanking duty cycle */
245 idealDutyCycle = c.c - ((c.m * idealHPeriod) / 1000);
246 }
247
248 /* Find the number of pixels in blanking time */
249 hBlankPixels = round((hTotalActivePixels * idealDutyCycle) /
250 ((100 - idealDutyCycle) * c.cellGran)) * c.cellGran;
251
252 /* Find the total number of pixels */
253 hTotalPixels = hTotalActivePixels + hBlankPixels;
254
255 /* Find the horizontal back porch */
256 hBackPorch = round((hBlankPixels / 2) / c.cellGran) * c.cellGran;
257
258 /* Find the horizontal sync width */
259 hSyncWidth = round(((c.hSync/100) * hTotalPixels) / c.cellGran) * c.cellGran;
260
261 /* Find the horizontal sync + back porch */
262 hSyncBP = hBackPorch + hSyncWidth;
263
264 if (type == GTF_lockPF) {
265 /* Find the horizontal frequency */
266 hFreq = (dotClock / hTotalPixels) * 1000;
267
268 /* Find the number of lines in vSync + back porch */
269 vSyncBP = round((c.minVSyncBP * hFreq) / 1000);
270
271 /* Find the number of lines in the V back porch alone */
272 vBackPorch = vSyncBP - c.vSyncRqd;
273
274 /* Find the total number of lines in the vertical period */
275 vTotalLines = vLines + topMarginLines + botMarginLines + vSyncBP
276 + interlace + c.minPorch;
277
278 /* Find the actual vertical field frequency */
279 vFieldRate = (hFreq / vTotalLines) * 1000;
280 }
281 else {
282 if (type == GTF_lockVF) {
283 /* Find the horizontal frequency */
284 hFreq = 1000 / hPeriod;
285 }
286 else if (type == GTF_lockHF) {
287 /* Find the horizontal frequency */
288 hPeriod = 1000 / hFreq;
289 }
290
291 /* Find the pixel clock frequency */
292 dotClock = hTotalPixels / hPeriod;
293 }
294
295 /* Return the computed frequencies */
296 t->vFreq = vFieldRate;
297 t->hFreq = hFreq;
298 t->dotClock = dotClock;
299
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;
308
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;
317 if (wantInterlace) {
318 /* Halve the timings for interlaced modes */
319 t->v.vTotal /= 2;
320 t->v.vDisp /= 2;
321 t->v.vSyncStart /= 2;
322 t->v.vSyncEnd /= 2;
323 t->v.vFrontPorch /= 2;
324 t->v.vSyncWidth /= 2;
325 t->v.vBackPorch /= 2;
326 t->dotClock /= 2;
327 }
328
329 /* Mark as GTF timing using the sync polarities */
330 t->interlace = (wantInterlace) ? 'I' : 'N';
331 t->hSyncPol = '-';
332 t->vSyncPol = '+';
333 }
334
335 void GTF_getConstants(GTF_constants *constants)
336 { *constants = GC; }
337
338 void GTF_setConstants(GTF_constants *constants)
339 { GC = *constants; }
340
341 #ifdef TESTING_GTF
342
343 void main(int argc,char *argv[])
344 {
345 FILE *f;
346 double xPixels,yPixels,freq;
347 ibool interlace;
348 GTF_timings t;
349
350 if (argc != 5 && argc != 6) {
351 printf("Usage: GTFCALC <xPixels> <yPixels> <freq> [[Hz] [KHz] [MHz]] [I]\n");
352 printf("\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");
358 printf("\n");
359 printf("For example to generate timings for 640x480 at 60Hz vertical:\n");
360 printf("\n");
361 printf(" GTFCALC 640 480 60 Hz\n");
362 printf("\n");
363 printf("For example to generate timings for 640x480 at 31.5KHz horizontal:\n");
364 printf("\n");
365 printf(" GTFCALC 640 480 31.5 KHz\n");
366 printf("\n");
367 printf("For example to generate timings for 640x480 with a 25.175Mhz dot clock:\n");
368 printf("\n");
369 printf(" GTFCALC 640 480 25.175 MHz\n");
370 printf("\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");
373 exit(1);
374 }
375
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'));
381
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);
389 else {
390 printf("Unknown command line!\n");
391 exit(1);
392 }
393
394 /* Dump summary info to standard output */
395 printf("CRTC values for %.0fx%.0f @ %.2f %s\n", xPixels, yPixels, freq, argv[4]);
396 printf("\n");
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);
411 printf("\n");
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);
415 printf("\n");
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);
419
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,
430 t.vSyncPol);
431 fprintf(f, "%.2f\n", t.dotClock);
432 fclose(f);
433 }
434 }
435
436 #endif /* TESTING */