makemodes.awk revision 1.4 1 # $NetBSD: makemodes.awk,v 1.4 2006/08/17 22:33:59 bjh21 Exp $
2
3 #
4 # Copyright (c) 1998 The NetBSD Foundation, Inc.
5 # All rights reserved.
6 #
7 # This code is derived from software contributed to The NetBSD Foundation
8 # by Mark Brinicombe
9 #
10 # Redistribution and use in source and binary forms, with or without
11 # modification, are permitted provided that the following conditions
12 # are met:
13 # 1. Redistributions of source code must retain the above copyright
14 # notice, this list of conditions and the following disclaimer.
15 # 2. Redistributions in binary form must reproduce the above copyright
16 # notice, this list of conditions and the following disclaimer in the
17 # documentation and/or other materials provided with the distribution.
18 # 3. All advertising materials mentioning features or use of this software
19 # must display the following acknowledgement:
20 # This product includes software developed by the NetBSD
21 # Foundation, Inc. and its contributors.
22 # 4. Neither the name of The NetBSD Foundation nor the names of its
23 # contributors may be used to endorse or promote products derived
24 # from this software without specific prior written permission.
25 #
26 # THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
27 # ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
28 # TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
29 # PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
30 # BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
31 # CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
32 # SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
33 # INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
34 # CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
35 # ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
36 # POSSIBILITY OF SUCH DAMAGE.
37 #
38
39 # This parses a Acorn monitor definition file and constructs an array of
40 # parameters for each mode.
41 # Once the file has been parsed the list of modes is examined to find modes
42 # that match the mode specifications specified on the command line.
43 # The matching mode definitions are written to stdout in the form of a C file.
44 # Parsing information is written to stderr.
45 #
46 #
47 # Syntax for using this program
48 #
49 # awk -f makemodes.awk <MDF file> <mode spec> [<mode spec> ...]
50 #
51 # where <mode spec> is
52 # <x>,<y>
53 # <x>,<y>,<f>
54 # <x>,<y>,<c>,<f>
55 #
56 # Note: Spaces are NOT allowed in a mode specifier
57 #
58 # where x = x resolution
59 # y = y resolution
60 # f = frame rate
61 # c = colour depth (16, 256, 32768, 65536)
62 #
63
64 BEGIN {
65 # Number of modes parsed and valid in the modes array.
66 mode = 0;
67
68 # MDF file globals
69 monitor = "";
70 dpms = 0;
71
72 # Non zero if we are translating a mode
73 translate = 0;
74
75 # ':' character is used to separate the tokens.
76 FS=":";
77
78 # Note the real number of arguments and truncate ARGC so that only the first
79 # argument is used as a filename.
80 realargc = ARGC;
81 ARGC=2;
82
83 # Translation of sync_pol to videomode.flags
84 pol[0] = "HP|VP";
85 pol[1] = "HN|VP";
86 pol[2] = "HP|VN";
87 pol[3] = "HN|VN";
88 }
89
90 # MDF File format
91 /^file_format/ {
92 # Currently we only understand format 1 MDF files
93 if ($2 != 1) {
94 printf("Unrecognised MDF format (%d)\n", $2);
95 exit;
96 }
97 }
98
99 # Monitor name
100 /^monitor_title/ {
101 monitor = $2;
102 }
103
104 # Monitor DPMS state
105 /^DPMS_state/ {
106 dpms = $2;
107 }
108
109 # Start of mode definition
110 /^startmode/ {
111 translate = 1;
112 }
113
114 # End of mode definition
115 /^endmode/ {
116 translate = 0;
117 mode = mode + 1;
118 }
119
120 # The mode definition name (only valid within startmode/endmode section)
121 /^mode_name:/ {
122 if (!translate)
123 next;
124 modes[mode, 0] = $2;
125 next;
126 }
127
128 # The horizontal resolution (only valid within startmode/endmode section)
129 /^x_res:/ {
130 if (!translate)
131 next;
132 modes[mode, 1] = $2;
133 next;
134 }
135
136 # The vertical resolution (only valid within startmode/endmode section)
137 /^y_res:/ {
138 if (!translate)
139 next;
140 modes[mode, 2] = $2;
141 next;
142 }
143
144 # The pixel rate (only valid within startmode/endmode section)
145 /^pixel_rate:/ {
146 if (!translate)
147 next;
148 modes[mode, 3] = $2;
149 next;
150 }
151
152 # The horizontal timings (only valid within startmode/endmode section)
153 /^h_timings:/ {
154 if (!translate)
155 next;
156 modes[mode, 4] = $2;
157 next;
158 }
159
160 # The vertical timings (only valid within startmode/endmode section)
161 /^v_timings:/ {
162 if (!translate)
163 next;
164 modes[mode, 5] = $2;
165 next;
166 }
167
168 # The sync polarity (only valid within startmode/endmode section)
169 /^sync_pol:/ {
170 if (!translate)
171 next;
172 modes[mode, 6] = $2;
173 next;
174 }
175
176 END {
177 #
178 # Now generate the C file
179 #
180
181 # Create the file header
182 printf("/*\n");
183 printf(" * MACHINE GENERATED: DO NOT EDIT\n");
184 printf(" *\n");
185 printf(" * Created from %s\n", FILENAME);
186 printf(" */\n\n");
187 printf("#include <sys/types.h>\n");
188 printf("#include <arm/iomd/vidc.h>\n\n");
189 printf("const char *monitor = \"%s\";\n", monitor);
190 printf("const int dpms = %d;\n", dpms);
191 printf("#define HP VID_PHSYNC\n");
192 printf("#define HN VID_NHSYNC\n");
193 printf("#define VP VID_PVSYNC\n");
194 printf("#define VN VID_NVSYNC\n");
195 printf("\n");
196
197 # Now define the modes array
198 printf("struct vidc_mode vidcmodes[] = {\n");
199
200 # Loop round all the modespecs on the command line
201 for (res = 2; res < realargc; res = res + 1) {
202 pos = -1;
203 found = -1;
204 closest = 200;
205
206 # Report the mode specifier being processed
207 printf("%s ==> ", ARGV[res]) | "cat 1>&2";
208
209 # Pull apart the modespec
210 args = split(ARGV[res], modespec, ",");
211
212 # We need at least 2 arguments
213 if (args < 2) {
214 printf("Invalid mode specifier\n") | "cat 1>&2";
215 continue;
216 }
217
218 # If we only have x,y default c and f
219 if (args == 2) {
220 modespec[3] = 256;
221 modespec[4] = -1;
222 }
223 # If we have x,y,f default c and re-arrange.
224 if (args == 3) {
225 modespec[4] = modespec[3];
226 modespec[3] = 256;
227 }
228
229 # Report the full mode specifier
230 printf("%d x %d x %d x %d : ", modespec[1], modespec[2],
231 modespec[3], modespec[4]) | "cat 1>&2";
232
233 # Now loop round all the modes we parsed and find the matches
234 for (loop = 0; loop < mode; loop = loop + 1) {
235 # Match X & Y
236 if (modespec[1] != modes[loop, 1]) continue;
237 if (modespec[2] != modes[loop, 2]) continue;
238
239 # Split the horizontal and vertical timings
240 # This is needed for the frame rate calculation
241 ht = split(modes[loop, 4], htimings, ",");
242 if (ht != 6) continue;
243 vt = split(modes[loop, 5], vtimings, ",");
244 if (vt != 6) continue;
245
246 # Calculate the frame rate
247 fr = modes[loop, 3] / (htimings[1] + htimings[2] + \
248 htimings[3] + htimings[4] + htimings[5] + \
249 htimings[6]) / ( vtimings[1] + vtimings[2] + \
250 vtimings[3] + vtimings[4] + vtimings[5] + \
251 vtimings[6]);
252 fr = fr * 1000;
253
254 # Remember the frame rate
255 modes[loop, 7] = int(fr + 0.5);
256
257 # Create the internal version of the timings
258 modes[loop, "timings"] = \
259 sprintf( \
260 "{ %d, %d,%d,%d,%d, %d,%d,%d,%d, %s, \"%s\" }",\
261 modes[loop, 3], htimings[4], \
262 htimings[4] + htimings[5] + htimings[6], \
263 htimings[4] + htimings[5] + htimings[6] + \
264 htimings[1], \
265 htimings[4] + htimings[5] + htimings[6] + \
266 htimings[1] + htimings[2] + htimings[3], \
267 vtimings[4], \
268 vtimings[4] + vtimings[5] + vtimings[6], \
269 vtimings[4] + vtimings[5] + vtimings[6] + \
270 vtimings[1], \
271 vtimings[4] + vtimings[5] + vtimings[6] + \
272 vtimings[1] + vtimings[2] + vtimings[3], \
273 pol[modes[loop, 6]], modes[loop, 0]);
274
275 # Report the frame rate
276 printf("%d ", modes[loop, 7]) | "cat 1>&2";
277
278 # Is this the closest
279 if (closest > mod(modes[loop, 7] - modespec[4])) {
280 closest = mod(modes[loop, 7] - modespec[4]);
281 pos = loop;
282 }
283
284 # Do we have an exact match ?
285 if (modes[loop, 7] == modespec[4])
286 found = pos;
287 }
288
289 # If no exact match use the nearest
290 if (found == -1)
291 found = pos;
292
293 # Did we find any sort of match ?
294 if (found == -1) {
295 printf("Cannot find mode") | "cat 1>&2";
296 continue;
297 }
298
299 # Report the frame rate matched
300 printf("- %d", modes[found, 7]) | "cat 1>&2";
301
302 # Output the mode as part of the mode definition array
303 printf("\t{ %s,\n\t %d, %d },\n",
304 modes[found, "timings"], cdepth(modespec[3]),
305 modes[found, 7]);
306
307 printf("\n") | "cat 1>&2";
308 }
309
310 # Add a terminating entry and close the array.
311 printf("\t{ { 0 } }\n");
312 printf("};\n");
313 }
314
315 #
316 # cdepth() function
317 #
318 # This returns the colour depth as a power of 2 + 1
319 #
320 function cdepth(depth) {
321 if (depth == 16)
322 return 5;
323 if (depth == 256)
324 return 9;
325 if (depth == 32768)
326 return 16;
327 if (depth == 65536)
328 return 17;
329 return 9;
330 }
331
332 #
333 # Simple mod() function
334 #
335 function mod(a) {
336 if (a < 0)
337 return -a;
338 return a;
339 }
340