-
Notifications
You must be signed in to change notification settings - Fork 5
/
gnet_gsch2pcb.py
188 lines (163 loc) · 5.56 KB
/
gnet_gsch2pcb.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
# gaf.netlist - gEDA Netlist Extraction and Generation
# Copyright (C) 1998-2010 Ales Hvezda
# Copyright (C) 1998-2010 gEDA Contributors (see ChangeLog for details)
# Copyright (C) 2013-2020 Roland Lutz
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software Foundation,
# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
# gsch2pcb format (based on PCBboard format by JM Routoure & Stefan Petersen)
# Bill Wilson billw@wt.net
# 6/17/2003
import re, subprocess, sys
use_m4 = False
# Let the user override the m4 command, the directory
# where pcb stores its m4 files and the pcb config directory.
pcb_m4_command = '@m4@'
pcb_m4_dir = '@pcbm4dir@'
m4_files = []
# Let the user override the m4 search path
pcb_m4_path = ['$HOME/.pcb', '.']
RX = re.compile('^[A-Za-z0-9_]*$')
# Return the footprint for a package. If M4 footprints are enabled,
# writes in a format suitable for macro-expansion by M4. Any
# footprint names that obviously can't be M4 footprints are protected
# from macro-expansion.
def value_footprint(package):
value = package.get_attribute('value', 'unknown')
footprint = [x for x in package.get_attribute(
'footprint', 'unknown').split(' ') if x]
fp = footprint[0]
fp_args = footprint[1:]
nq = lambda x: x # A non-quoting operator
if use_m4:
# Quote a string to protect from M4 macro expansion
q = lambda x: "`%s'" % x # A quoting operator
else:
q = nq
# If the footprint is obviously not an M4 footprint,
# protect it from macro-expansion.
# Check if `str' contains only characters valid in an M4 function
# name. Note that this *doesn't* check that str is a valid M4
# function name.
if RX.match(fp) is not None:
fp_ = 'PKG_' + fp
else:
fp_ = q('PKG_' + fp)
return '%s(%s,%s,%s%s)\n' % (fp_,
q('-'.join(footprint)),
q(package.refdes),
q(value),
''.join(',' + q(arg) for arg in fp_args))
def run(f, netlist):
# Build list of the m4 argument vector
m4_command_line_list = \
[pcb_m4_command, '-d'] + \
['-I' + d for d in [pcb_m4_dir] + pcb_m4_path] + \
[pcb_m4_dir + '/common.m4'] + m4_files + ['-']
sys.stderr.write(MESSAGE % (pcb_m4_command,
pcb_m4_dir,
', '.join('"%s"' % s for s in pcb_m4_path),
', '.join('"%s"' % s for s in m4_files),
{ True: 'yes', False: 'no' }[use_m4],
' '.join(m4_command_line_list)))
f.write(TOP_HEADER)
# If we have defined use_m4 then run the footprints
# through the pcb m4 setup. Otherwise skip m4 entirely
if use_m4:
sys.stderr.write("Using the m4 processor for pcb footprints\n")
f.flush()
p = subprocess.Popen(m4_command_line_list,
stdin = subprocess.PIPE,
stdout = f.fileno(),
close_fds = True)
for package in reversed(netlist.packages):
p.stdin.write(value_footprint(package))
p.stdin.close()
status = p.wait()
if status != 0:
sys.stderr.write("%s returned exit status %d\n"
% (pcb_m4_command, status))
netlist.failed = True
return
else:
sys.stderr.write("Skipping the m4 processor for pcb footprints\n")
for package in reversed(netlist.packages):
f.write(value_footprint(package))
f.write(BOTTOM_FOOTER)
MESSAGE = """\
=====================================================
gsch2pcb backend configuration:
----------------------------------------
Variables which may be changed in gafrc:
----------------------------------------
pcb_m4_command: %s
pcb_m4_dir: %s
pcb_m4_path: %s
m4_files: %s
---------------------------------------------------
Variables which may be changed in the project file:
---------------------------------------------------
use_m4: %s
----------------
M4 command line:
----------------
%s
=====================================================
"""
TOP_HEADER = """\
# release: pcb 1.99x
# To read pcb files, the pcb version (or the cvs source date) must be >= the file version
FileVersion[20070407]
PCB["" 600000 500000]
Grid[10000.000000 0 0 0]
Cursor[0 0 0.000000]
PolyArea[200000000.000000]
Thermal[0.500000]
DRC[1000 1000 1000 1000 1500 1000]
Flags("nameonpcb,uniquename,clearnew,snappin")
Groups("1,c:2:3:4:5:6,s:7:8")
Styles["Signal,1000,3600,2000,1000:Power,2500,6000,3500,1000:Fat,4000,6000,3500,1000:Skinny,600,2402,1181,600"]
"""
BOTTOM_FOOTER = """\
Layer(1 "top")
(
)
Layer(2 "ground")
(
)
Layer(3 "signal2")
(
)
Layer(4 "signal3")
(
)
Layer(5 "power")
(
)
Layer(6 "bottom")
(
)
Layer(7 "outline")
(
)
Layer(8 "spare")
(
)
Layer(9 "silk")
(
)
Layer(10 "silk")
(
)
"""