xref: /netbsd/sys/arch/arm/iomd/makemodes.awk (revision bf9ec67e)
1#	$NetBSD: makemodes.awk,v 1.1 2001/10/05 22:27:41 reinoud 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
64BEGIN {
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
84# MDF File format
85/^file_format/ {
86	# Currently we only understand format 1 MDF files
87	if ($2 != 1) {
88		printf("Unrecognised MDF format (%d)\n", $2);
89		exit;
90	}
91}
92
93# Monitor name
94/^monitor_title/ {
95	monitor = $2;
96}
97
98# Monitor DPMS state
99/^DPMS_state/ {
100	dpms = $2;
101}
102
103# Start of mode definition
104/^startmode/ {
105	translate = 1;
106}
107
108# End of mode definition
109/^endmode/ {
110	translate = 0;
111	mode = mode + 1;
112}
113
114# The mode definition name (only valid within startmode/endmode section)
115/^mode_name:/ {
116	if (!translate)
117		next;
118	modes[mode, 0] = $2;
119	next;
120}
121
122# The horizontal resolution (only valid within startmode/endmode section)
123/^x_res:/ {
124	if (!translate)
125		next;
126	modes[mode, 1] = $2;
127	next;
128}
129
130# The vertical resolution (only valid within startmode/endmode section)
131/^y_res:/ {
132	if (!translate)
133		next;
134	modes[mode, 2] = $2;
135	next;
136}
137
138# The pixel rate (only valid within startmode/endmode section)
139/^pixel_rate:/ {
140	if (!translate)
141		next;
142	modes[mode, 3] = $2;
143	next;
144}
145
146# The horizontal timings (only valid within startmode/endmode section)
147/^h_timings:/ {
148	if (!translate)
149		next;
150	modes[mode, 4] = $2;
151	next;
152}
153
154# The vertical timings (only valid within startmode/endmode section)
155/^v_timings:/ {
156	if (!translate)
157		next;
158	modes[mode, 5] = $2;
159	next;
160}
161
162# The sync polarity (only valid within startmode/endmode section)
163/^sync_pol:/ {
164	if (!translate)
165		next;
166	modes[mode, 6] = $2;
167	next;
168}
169
170END {
171	#
172	# Now generate the C file
173	#
174
175	# Create the file header
176	printf("/*\n");
177	printf(" * MACHINE GENERATED: DO NOT EDIT\n");
178	printf(" *\n");
179	printf(" * Created from %s\n", FILENAME);
180	printf(" */\n\n");
181	printf("#include <sys/types.h>\n");
182	printf("#include <arm/iomd/vidc.h>\n\n");
183	printf("const char *monitor = \"%s\";\n", monitor);
184	printf("const int dpms = %d;\n", dpms);
185	printf("\n");
186
187	# Now define the modes array
188	printf("struct vidc_mode vidcmodes[] = {\n");
189
190	# Loop round all the modespecs on the command line
191	for (res = 2; res < realargc; res = res + 1) {
192		pos = -1;
193		found = -1;
194		closest = 200;
195
196		# Report the mode specifier being processed
197		printf("%s ==> ", ARGV[res]) > "/dev/stderr";
198
199		# Pull apart the modespec
200		args = split(ARGV[res], modespec, ",");
201
202		# We need at least 2 arguments
203		if (args < 2) {
204			printf("Invalid mode specifier\n") > "/dev/stderr";
205			continue;
206		}
207
208		# If we only have x,y default c and f
209		if (args == 2) {
210			modespec[3] = 256;
211			modespec[4] = -1;
212		}
213		# If we have x,y,f default c and re-arrange.
214		if (args == 3) {
215			modespec[4] = modespec[3];
216			modespec[3] = 256;
217		}
218
219		# Report the full mode specifier
220		printf("%d x %d x %d x %d : ", modespec[1], modespec[2],
221		    modespec[3], modespec[4]) > "/dev/stderr";
222
223		# Now loop round all the modes we parsed and find the matches
224		for (loop = 0; loop < mode; loop = loop + 1) {
225			# Match X & Y
226			if (modespec[1] != modes[loop, 1]) continue;
227			if (modespec[2] != modes[loop, 2]) continue;
228
229			# Split the horizontal and vertical timings
230			# This is needed for the frame rate calculation
231			ht = split(modes[loop, 4], htimings, ",");
232			if (ht != 6) continue;
233			vt = split(modes[loop, 5], vtimings, ",");
234			if (vt != 6) continue;
235
236			# Calculate the frame rate
237			fr = modes[loop, 3] / (htimings[1] + htimings[2] + \
238			    htimings[3] + htimings[4] + htimings[5] + \
239			    htimings[6]) / ( vtimings[1] + vtimings[2] + \
240			    vtimings[3] + vtimings[4] + vtimings[5] + \
241			    vtimgings[6]);
242			fr = fr * 1000;
243
244			# Remember the frame rate
245			modes[loop, 7] = int(fr + 0.5);
246
247			# Report the frame rate
248			printf("%d ", modes[loop, 7]) > "/dev/stderr";
249
250			# Is this the closest
251			if (closest > mod(modes[loop, 7] - modespec[4])) {
252				closest = mod(modes[loop, 7] - modespec[4]);
253				pos = loop;
254			}
255
256			# Do we have an exact match ?
257			if (modes[loop, 7] == modespec[4])
258				found = pos;
259		}
260
261		# If no exact match use the nearest
262		if (found == -1)
263			found = pos;
264
265		# Did we find any sort of match ?
266		if (found == -1) {
267			printf("Cannot find mode") > "/dev/stderr";
268			continue;
269		}
270
271		# Report the frame rate matched
272		printf("- %d", modes[found, 7]) > "/dev/stderr";
273
274		# Output the mode as part of the mode definition array
275		printf("\t{ %6d, %22s, %22s, %d, %d, %d },\n",
276		    modes[found, 3], modes[found, 4], modes[found, 5],
277		    cdepth(modespec[3]), modes[found, 6], modes[found, 7]);
278
279		printf("\n") > "/dev/stderr";
280	}
281
282	# Add a terminating entry and close the array.
283	printf("\t{ 0 }\n");
284	printf("};\n");
285}
286
287#
288# cdepth() function
289#
290# This returns the colour depth as a power of 2 + 1
291#
292function cdepth(depth) {
293	if (depth == 16)
294		return 5;
295	if (depth == 256)
296		return 9;
297	if (depth == 32768)
298		return 16;
299	if (depth == 65536)
300		return 17;
301	return 9;
302}
303
304#
305# Simple mod() function
306#
307function mod(a) {
308	if (a < 0)
309		return -a;
310	return a;
311}
312