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 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326
|
#-----------------------------------------------------------------------
# Set of Tcl procedures to convert an xcircuit schematic to an initial
# (unrouted) PCB layout.
#
# Written by Tim Edwards for MultiGiG Inc., February 27, 2004.
#-----------------------------------------------------------------------
#-----------------------------------------------------------------------
# Procedure to convert xcircuit strings to plain ASCII text.
#-----------------------------------------------------------------------
proc string_to_text {xcstr} {
set rst ""
foreach sst $xcstr {
switch -glob $sst {
Text* {
set atxt [lindex $sst 1]
append rst $atxt
}
}
}
return $rst
}
#-----------------------------------------------------------------------
# Procedure to map XCircuit names to PBC names. This is just a hack.
# Ideally, we would want an XCircuit library whose names map directly
# into the PCB library, so no translation is needed. There would be
# parameters for the description line, package line, and name line to
# be passed to the program.
#-----------------------------------------------------------------------
# Currently, understands 7400 series devices from the "diplib" and
# "newdiplib" libraries. ("DIP7400" or "dil_7400" maps to "7400_dil",
# and so forth).
#-----------------------------------------------------------------------
# Understanding of axial and SMD resistors and capacitors added
# 1/4/05. This is somewhat hacked-up. PCB has it backwards: The
# package type should be, e.g., "SMD_SIMPLE_603", not "SMD_SIMPLE",
# while the name should be "smd_resistor", not "smd_resistor_603".
#-----------------------------------------------------------------------
proc xcirc_to_pcbname {xcname {pkgparam ""}} {
switch -glob $xcname {
dil_* {
set lstyp [string range $xcname 4 end]
set rst "${lstyp}_dil"
}
DIP* {
set lstyp [string range $xcname 3 end]
set rst "${lstyp}_dil"
}
res* -
Res* {
switch -glob $pkgparam {
SMD* {
set lpos [string last "_" $pkgparam]
set pkgsize [string range $pkgparam $lpos end]
set rst "smd_resistor$pkgsize"
}
AXIAL* {
set lpos [string last "_" $pkgparam]
set pkgsize [string range $pkgparam $lpos end]
set rst "generic_resistor_axial$pkgsize"
}
default {
set rst "generic_resistor_axial_400"
}
}
}
cap* -
Cap* {
switch -glob $pkgparam {
SMD* {
set lpos [string last "_" $pkgparam]
set pkgsize [string range $pkgparam $lpos end]
set rst "smd_capacitor$pkgsize"
}
AXIAL* {
set lpos [string last "_" $pkgparam]
set pkgsize [string range $pkgparam $lpos end]
set rst "generic_capacitor_axial$pkgsize"
}
default {
set rst "generic_capacitor_axial_400"
}
}
}
default {set rst $xcname}
}
return $rst
}
#-----------------------------------------------------------------------
# Procedure to map XCircuit names to PCB package names.
#-----------------------------------------------------------------------
# Currently, understands DIP packages (7400 series)
#-----------------------------------------------------------------------
proc xcirc_to_pkgname {pkgparam numpins} {
switch -glob $pkgparam {
DIP {set rst "DIP$numpins"}
SMD* {set rst SMD_SIMPLE}
AXIAL* {set rst AXIAL_LAY}
default {set rst $pkgparam}
}
return $rst
}
#-----------------------------------------------------------------------
# Add an element to the (open) pcb file
#-----------------------------------------------------------------------
proc add_pcb_element {fileId element numpins devname pkgparam} {
global PCBLIBDIR SUBDIR GEN_ELEM_SCRIPT
set pcbelem [xcirc_to_pcbname $element $pkgparam]
set pkgname [xcirc_to_pkgname $pkgparam $numpins]
set elist [exec ${PCBLIBDIR}/${GEN_ELEM_SCRIPT} ${PCBLIBDIR} ${SUBDIR} \
$pcbelem $element $pkgname]
eval [subst {regsub {""} \$elist {"$devname"} efinal}]
puts stdout "IN: QueryLibrary.sh pcblib $pcbelem $element $pkgname"
puts stdout "OUT: $efinal"
puts $fileId $efinal
}
#-----------------------------------------------------------------------
# Generate elements from the xcircuit schematic
#
# This assumes a pcb-like schematic, with a flat schematic. Needs to be
# expanded to handle hierarchical schematics. This will work with
# multipage schematics.
#
# For now, this only supports 7400 series devices, so we can assume that
# the string is "U". However, different packages of the devices can be
# specified, and any device name can be processed as long as it has a
# valid package type (DIL, SO, US, etc.).
#
# Extended 1/4/05 to handle resistors and capacitors.
#-----------------------------------------------------------------------
proc gen_pcb_elements {fileId} {
set numpins 0
set pkgname "unknown"
set nl [netlist make]
set ckt [lindex $nl 3]
foreach subckt $ckt {
set ename "default"
# MUST parse in order: name, device, (everything else)
foreach {key value} $subckt {
switch -- $key {
name {
set ename $value
break;
}
}
}
foreach {key value} $subckt {
switch -- $key {
devices {
foreach dev $value {
foreach tpart $dev {
set ascl [string_to_text $tpart]
set cpos [string first "pcb:" $ascl]
if {$cpos >= 0} {
set defpfix($ename) [string range $ascl 4 end]
break
}
}
}
}
}
}
foreach {key value} $subckt {
switch -- $key {
name {set ename $value}
ports {set defpins($ename) [expr {[llength $value] / 2}]}
parameters {
foreach {pkey pval} $value {
switch -- $pkey {
idx -
v1 {
set devnum [string_to_text $pval]
set defnum($ename) "${devnum}"
}
pkg {
set defpkg($ename) [string_to_text $pval]
}
}
}
}
}
}
}
set top [lindex $ckt [expr {[llength $ckt] - 1}]]
foreach {key calllist} $top {
if {$key == "calls"} {break}
}
set devnum 0
foreach call $calllist {
set numpins 0
incr devnum
set devpfix "U"
set devname "U?"
set pkgname "unknown"
set ename "default"
foreach {key value} $call {
switch -- $key {
name {
set ename $value
catch {set numpins $defpins($ename)}
catch {set devpfix $defpfix($ename)}
catch {set pkgname $defpkg($ename)}
catch {set locdevnum $defnum($ename); \
set devname ${devpfix}${locdevnum}}
}
ports {set numpins [expr {[llength $value] / 2}]}
parameters {
foreach {pkey pval} $value {
switch -- $pkey {
idx -
v1 {
set locdevnum [string_to_text $pval]
set devname "${devpfix}${locdevnum}"
}
pkg {
set pkgname [string_to_text $pval]
}
}
}
}
}
}
if {[string range $devname end end] == "?"} {set devname "${devpfix}${devnum}"}
add_pcb_element $fileId $ename $numpins $devname $pkgname
}
}
#-----------------------------------------------------------------------
# Tcl procedure to write an xcircuit layout to an initial PCB layout.
#-----------------------------------------------------------------------
proc xcirc_to_pcb {filename} {
global PCBLIBDIR SUBDIR GEN_ELEM_SCRIPT
# Open the pcb file and generate a valid header
set fileId [open $filename w 0600]
puts $fileId "PCB(\"\" 6000 5000)"
puts $fileId ""
puts $fileId "Grid(10 0 0 0)"
puts $fileId "Cursor(160 690 3)"
puts $fileId "Flags(0x00000000000006d0)"
puts $fileId "Groups(\"1,s:2,c:3:4:5:6:7:8\")"
puts $fileId "Styles(\"Signal,10,55,28,10:Power,25,60,35,10:Fat,40,60,35,10:Skinny,8,36,20,7\")"
puts $fileId ""
# Generate elements
gen_pcb_elements $fileId
# Generate a valid trailer and close the pcb file
puts $fileId ""
puts $fileId "Layer(1 \"solder\")"
puts $fileId "("
puts $fileId ")"
puts $fileId "Layer(2 \"component\")"
puts $fileId "("
puts $fileId ")"
puts $fileId "Layer(3 \"GND\")"
puts $fileId "("
puts $fileId ")"
puts $fileId "Layer(4 \"power\")"
puts $fileId "("
puts $fileId ")"
puts $fileId "Layer(5 \"signal1\")"
puts $fileId "("
puts $fileId ")"
puts $fileId "Layer(6 \"signal2\")"
puts $fileId "("
puts $fileId ")"
puts $fileId "Layer(7 \"unused\")"
puts $fileId "("
puts $fileId ")"
puts $fileId "Layer(8 \"unused\")"
puts $fileId "("
puts $fileId ")"
puts $fileId "Layer(9 \"silk\")"
puts $fileId "("
puts $fileId ")"
puts $fileId "Layer(10 \"silk\")"
puts $fileId "("
puts $fileId ")"
close $fileId
}
#-----------------------------------------------------------------------
# Create a dialog for querying the name of the output layout file
#-----------------------------------------------------------------------
proc xcircuit::promptpcblayout {} {
.dialog.bbar.okay configure -command \
{xcirc_to_pcb [.dialog.textent.txt get]; wm withdraw .dialog}
.dialog.textent.title.field configure -text "Enter name for PCB layout:"
.dialog.textent.txt delete 0 end
set lname [xcircuit::page label]
append lname ".pcb"
.dialog.textent.txt insert 0 $lname
wm deiconify .dialog
focus .dialog.textent.txt
}
# These may be reset at any time. . .
set PCBLIBDIR "/usr/local/share/pcb/"
set SUBDIR "pcblib"
set GEN_ELEM_SCRIPT "QueryLibrary.sh"
#-----------------------------------------------------------------------
# Add the PCB layout command to the XCircuit "Netlist" menu.
#-----------------------------------------------------------------------
set m .xcircuit.menubar.netlistbutton.netlistmenu
$m add command -label "Create PCB Layout" -command {xcircuit::promptpcblayout}
#-----------------------------------------------------------------------
|