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