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
} {
17 set atxt
[lindex $sst 1]
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",
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 {
45 set lstyp
[string range
$xcname 4 end
]
46 set rst
"${lstyp}_dil"
49 set lstyp
[string range
$xcname 3 end
]
50 set rst
"${lstyp}_dil"
54 switch -glob $pkgparam {
56 set lpos
[string last
"_" $pkgparam]
57 set pkgsize
[string range
$pkgparam $lpos end
]
58 set rst
"smd_resistor$pkgsize"
61 set lpos
[string last
"_" $pkgparam]
62 set pkgsize
[string range
$pkgparam $lpos end
]
63 set rst
"generic_resistor_axial$pkgsize"
66 set rst
"generic_resistor_axial_400"
72 switch -glob $pkgparam {
74 set lpos
[string last
"_" $pkgparam]
75 set pkgsize
[string range
$pkgparam $lpos end
]
76 set rst
"smd_capacitor$pkgsize"
79 set lpos
[string last
"_" $pkgparam]
80 set pkgsize
[string range
$pkgparam $lpos end
]
81 set rst
"generic_capacitor_axial$pkgsize"
84 set rst
"generic_capacitor_axial_400"
88 default {set rst
$xcname}
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}
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"
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
} {
142 set pkgname
"unknown"
144 set nl
[netlist make
]
145 set ckt
[lindex $nl 3]
147 foreach subckt
$ckt {
149 # MUST parse in order: name, device, (everything else)
150 foreach {key value
} $subckt {
158 foreach {key value
} $subckt {
163 set ascl
[string_to_text
$tpart]
164 set cpos
[string first
"pcb:" $ascl]
166 set defpfix
($ename) [string range
$ascl 4 end
]
174 foreach {key value
} $subckt {
176 name
{set ename
$value}
177 ports
{set defpins
($ename) [expr {[llength $value] / 2}]}
179 foreach {pkey pval
} $value {
183 set devnum
[string_to_text
$pval]
184 set defnum
($ename) "${devnum}"
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}
201 foreach call
$calllist {
206 set pkgname
"unknown"
208 foreach {key value
} $call {
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}]}
220 foreach {pkey pval
} $value {
224 set locdevnum
[string_to_text
$pval]
225 set devname
"${devpfix}${locdevnum}"
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)"
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\")"
259 gen_pcb_elements
$fileId
261 # Generate a valid trailer and close the pcb file
264 puts $fileId "Layer(1 \"solder\")"
267 puts $fileId "Layer(2 \"component\")"
270 puts $fileId "Layer(3 \"GND\")"
273 puts $fileId "Layer(4 \"power\")"
276 puts $fileId "Layer(5 \"signal1\")"
279 puts $fileId "Layer(6 \"signal2\")"
282 puts $fileId "Layer(7 \"unused\")"
285 puts $fileId "Layer(8 \"unused\")"
288 puts $fileId "Layer(9 \"silk\")"
291 puts $fileId "Layer(10 \"silk\")"
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]
308 .dialog.textent.txt insert
0 $lname
310 focus .dialog.textent.txt
313 # These may be reset at any time. . .
315 set PCBLIBDIR
"/usr/local/share/pcb/"
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 #-----------------------------------------------------------------------