One more check on valid display which is known to be in the startup
[xcircuit.git] / lib / tcl / pcbout.tcl
blobc9c5ebeab492145245e661b8d1061f8d728a6383
1 #-----------------------------------------------------------------------
2 # Set of Tcl procedures to convert an xcircuit schematic to an initial
3 # (unrouted) PCB layout.
5 # Written by Tim Edwards for MultiGiG Inc., February 27, 2004.
6 #-----------------------------------------------------------------------
8 #-----------------------------------------------------------------------
9 # Procedure to convert xcircuit strings to plain ASCII text.
10 #-----------------------------------------------------------------------
12 proc string_to_text {xcstr} {
13 set rst ""
14 foreach sst $xcstr {
15 switch -glob $sst {
16 Text* {
17 set atxt [lindex $sst 1]
18 append rst $atxt
22 return $rst
25 #-----------------------------------------------------------------------
26 # Procedure to map XCircuit names to PBC names. This is just a hack.
27 # Ideally, we would want an XCircuit library whose names map directly
28 # into the PCB library, so no translation is needed. There would be
29 # parameters for the description line, package line, and name line to
30 # be passed to the program.
31 #-----------------------------------------------------------------------
32 # Currently, understands 7400 series devices from the "diplib" and
33 # "newdiplib" libraries. ("DIP7400" or "dil_7400" maps to "7400_dil",
34 # and so forth).
35 #-----------------------------------------------------------------------
36 # Understanding of axial and SMD resistors and capacitors added
37 # 1/4/05. This is somewhat hacked-up. PCB has it backwards: The
38 # package type should be, e.g., "SMD_SIMPLE_603", not "SMD_SIMPLE",
39 # while the name should be "smd_resistor", not "smd_resistor_603".
40 #-----------------------------------------------------------------------
42 proc xcirc_to_pcbname {xcname {pkgparam ""}} {
43 switch -glob $xcname {
44 dil_* {
45 set lstyp [string range $xcname 4 end]
46 set rst "${lstyp}_dil"
48 DIP* {
49 set lstyp [string range $xcname 3 end]
50 set rst "${lstyp}_dil"
52 res* -
53 Res* {
54 switch -glob $pkgparam {
55 SMD* {
56 set lpos [string last "_" $pkgparam]
57 set pkgsize [string range $pkgparam $lpos end]
58 set rst "smd_resistor$pkgsize"
60 AXIAL* {
61 set lpos [string last "_" $pkgparam]
62 set pkgsize [string range $pkgparam $lpos end]
63 set rst "generic_resistor_axial$pkgsize"
65 default {
66 set rst "generic_resistor_axial_400"
70 cap* -
71 Cap* {
72 switch -glob $pkgparam {
73 SMD* {
74 set lpos [string last "_" $pkgparam]
75 set pkgsize [string range $pkgparam $lpos end]
76 set rst "smd_capacitor$pkgsize"
78 AXIAL* {
79 set lpos [string last "_" $pkgparam]
80 set pkgsize [string range $pkgparam $lpos end]
81 set rst "generic_capacitor_axial$pkgsize"
83 default {
84 set rst "generic_capacitor_axial_400"
88 default {set rst $xcname}
90 return $rst
93 #-----------------------------------------------------------------------
94 # Procedure to map XCircuit names to PCB package names.
95 #-----------------------------------------------------------------------
96 # Currently, understands DIP packages (7400 series)
97 #-----------------------------------------------------------------------
99 proc xcirc_to_pkgname {pkgparam numpins} {
100 switch -glob $pkgparam {
101 DIP {set rst "DIP$numpins"}
102 SMD* {set rst SMD_SIMPLE}
103 AXIAL* {set rst AXIAL_LAY}
104 default {set rst $pkgparam}
106 return $rst
109 #-----------------------------------------------------------------------
110 # Add an element to the (open) pcb file
111 #-----------------------------------------------------------------------
113 proc add_pcb_element {fileId element numpins devname pkgparam} {
114 global PCBLIBDIR SUBDIR GEN_ELEM_SCRIPT
115 set pcbelem [xcirc_to_pcbname $element $pkgparam]
116 set pkgname [xcirc_to_pkgname $pkgparam $numpins]
117 set elist [exec ${PCBLIBDIR}/${GEN_ELEM_SCRIPT} ${PCBLIBDIR} ${SUBDIR} \
118 $pcbelem $element $pkgname]
119 eval [subst {regsub {""} \$elist {"$devname"} efinal}]
120 puts stdout "IN: QueryLibrary.sh pcblib $pcbelem $element $pkgname"
121 puts stdout "OUT: $efinal"
122 puts $fileId $efinal
125 #-----------------------------------------------------------------------
126 # Generate elements from the xcircuit schematic
128 # This assumes a pcb-like schematic, with a flat schematic. Needs to be
129 # expanded to handle hierarchical schematics. This will work with
130 # multipage schematics.
132 # For now, this only supports 7400 series devices, so we can assume that
133 # the string is "U". However, different packages of the devices can be
134 # specified, and any device name can be processed as long as it has a
135 # valid package type (DIL, SO, US, etc.).
137 # Extended 1/4/05 to handle resistors and capacitors.
138 #-----------------------------------------------------------------------
140 proc gen_pcb_elements {fileId} {
141 set numpins 0
142 set pkgname "unknown"
144 set nl [netlist make]
145 set ckt [lindex $nl 3]
147 foreach subckt $ckt {
148 set ename "default"
149 # MUST parse in order: name, device, (everything else)
150 foreach {key value} $subckt {
151 switch -- $key {
152 name {
153 set ename $value
154 break;
158 foreach {key value} $subckt {
159 switch -- $key {
160 devices {
161 foreach dev $value {
162 foreach tpart $dev {
163 set ascl [string_to_text $tpart]
164 set cpos [string first "pcb:" $ascl]
165 if {$cpos >= 0} {
166 set defpfix($ename) [string range $ascl 4 end]
167 break
174 foreach {key value} $subckt {
175 switch -- $key {
176 name {set ename $value}
177 ports {set defpins($ename) [expr {[llength $value] / 2}]}
178 parameters {
179 foreach {pkey pval} $value {
180 switch -- $pkey {
181 idx -
182 v1 {
183 set devnum [string_to_text $pval]
184 set defnum($ename) "${devnum}"
186 pkg {
187 set defpkg($ename) [string_to_text $pval]
196 set top [lindex $ckt [expr {[llength $ckt] - 1}]]
197 foreach {key calllist} $top {
198 if {$key == "calls"} {break}
200 set devnum 0
201 foreach call $calllist {
202 set numpins 0
203 incr devnum
204 set devpfix "U"
205 set devname "U?"
206 set pkgname "unknown"
207 set ename "default"
208 foreach {key value} $call {
209 switch -- $key {
210 name {
211 set ename $value
212 catch {set numpins $defpins($ename)}
213 catch {set devpfix $defpfix($ename)}
214 catch {set pkgname $defpkg($ename)}
215 catch {set locdevnum $defnum($ename); \
216 set devname ${devpfix}${locdevnum}}
218 ports {set numpins [expr {[llength $value] / 2}]}
219 parameters {
220 foreach {pkey pval} $value {
221 switch -- $pkey {
222 idx -
223 v1 {
224 set locdevnum [string_to_text $pval]
225 set devname "${devpfix}${locdevnum}"
227 pkg {
228 set pkgname [string_to_text $pval]
235 if {[string range $devname end end] == "?"} {set devname "${devpfix}${devnum}"}
236 add_pcb_element $fileId $ename $numpins $devname $pkgname
240 #-----------------------------------------------------------------------
241 # Tcl procedure to write an xcircuit layout to an initial PCB layout.
242 #-----------------------------------------------------------------------
244 proc xcirc_to_pcb {filename} {
245 global PCBLIBDIR SUBDIR GEN_ELEM_SCRIPT
247 # Open the pcb file and generate a valid header
248 set fileId [open $filename w 0600]
249 puts $fileId "PCB(\"\" 6000 5000)"
250 puts $fileId ""
251 puts $fileId "Grid(10 0 0 0)"
252 puts $fileId "Cursor(160 690 3)"
253 puts $fileId "Flags(0x00000000000006d0)"
254 puts $fileId "Groups(\"1,s:2,c:3:4:5:6:7:8\")"
255 puts $fileId "Styles(\"Signal,10,55,28,10:Power,25,60,35,10:Fat,40,60,35,10:Skinny,8,36,20,7\")"
256 puts $fileId ""
258 # Generate elements
259 gen_pcb_elements $fileId
261 # Generate a valid trailer and close the pcb file
263 puts $fileId ""
264 puts $fileId "Layer(1 \"solder\")"
265 puts $fileId "("
266 puts $fileId ")"
267 puts $fileId "Layer(2 \"component\")"
268 puts $fileId "("
269 puts $fileId ")"
270 puts $fileId "Layer(3 \"GND\")"
271 puts $fileId "("
272 puts $fileId ")"
273 puts $fileId "Layer(4 \"power\")"
274 puts $fileId "("
275 puts $fileId ")"
276 puts $fileId "Layer(5 \"signal1\")"
277 puts $fileId "("
278 puts $fileId ")"
279 puts $fileId "Layer(6 \"signal2\")"
280 puts $fileId "("
281 puts $fileId ")"
282 puts $fileId "Layer(7 \"unused\")"
283 puts $fileId "("
284 puts $fileId ")"
285 puts $fileId "Layer(8 \"unused\")"
286 puts $fileId "("
287 puts $fileId ")"
288 puts $fileId "Layer(9 \"silk\")"
289 puts $fileId "("
290 puts $fileId ")"
291 puts $fileId "Layer(10 \"silk\")"
292 puts $fileId "("
293 puts $fileId ")"
294 close $fileId
297 #-----------------------------------------------------------------------
298 # Create a dialog for querying the name of the output layout file
299 #-----------------------------------------------------------------------
301 proc xcircuit::promptpcblayout {} {
302 .dialog.bbar.okay configure -command \
303 {xcirc_to_pcb [.dialog.textent.txt get]; wm withdraw .dialog}
304 .dialog.textent.title.field configure -text "Enter name for PCB layout:"
305 .dialog.textent.txt delete 0 end
306 set lname [xcircuit::page label]
307 append lname ".pcb"
308 .dialog.textent.txt insert 0 $lname
309 wm deiconify .dialog
310 focus .dialog.textent.txt
313 # These may be reset at any time. . .
315 set PCBLIBDIR "/usr/local/share/pcb/"
316 set SUBDIR "pcblib"
317 set GEN_ELEM_SCRIPT "QueryLibrary.sh"
319 #-----------------------------------------------------------------------
320 # Add the PCB layout command to the XCircuit "Netlist" menu.
321 #-----------------------------------------------------------------------
323 set m .xcircuit.menubar.netlistbutton.netlistmenu
324 $m add command -label "Create PCB Layout" -command {xcircuit::promptpcblayout}
326 #-----------------------------------------------------------------------