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