]> git.sur5r.net Git - u-boot/blob - board/MAI/bios_emulator/scitech/src/common/gtfcalc.c
* Code cleanup:
[u-boot] / 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 */