From 1bf6c604ddb905d6f6898b1472ac94d085f4b223 Mon Sep 17 00:00:00 2001 From: "Jan \"Yenya\" Kasprzak" Date: Fri, 15 Mar 2013 13:35:07 +0100 Subject: [PATCH] Makefile: panelized design for 5x5cm fab --- Makefile | 32 +++++++------- panel.pl | 126 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ panel2pcb | 99 ++++++++++++++++++++++++++++++++++++++++++ pcb2panel | 101 +++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 342 insertions(+), 16 deletions(-) create mode 100644 panel.pl create mode 100755 panel2pcb create mode 100755 pcb2panel diff --git a/Makefile b/Makefile index c17f0c4..674b7dc 100644 --- a/Makefile +++ b/Makefile @@ -2,13 +2,13 @@ WEB_DIR=/home/kas/html/tinyboard/ WEB_FILES=pcb-back.png pcb-front.png schematics.png schematics-power.png \ schematics-pin.png GERBER_FILES=\ - tinyboard.top.gbr \ - tinyboard.bottom.gbr \ - tinyboard.topmask.gbr \ - tinyboard.bottommask.gbr \ - tinyboard.topsilk.gbr \ - tinyboard.bottomsilk.gbr \ - tinyboard.plated-drill.cnc + tinyboard-panel.top.gbr \ + tinyboard-panel.bottom.gbr \ + tinyboard-panel.topmask.gbr \ + tinyboard-panel.bottommask.gbr \ + tinyboard-panel.topsilk.gbr \ + tinyboard-panel.bottomsilk.gbr \ + tinyboard-panel.plated-drill.cnc all: @echo "Usage: make [clean|web|gerber|fab|tinyboard.pcb]" @@ -43,18 +43,18 @@ schematics-pin.png: schematics.png gerber: $(GERBER_FILES) -$(GERBER_FILES): tinyboard.pcb - pcb -x gerber tinyboard.pcb +$(GERBER_FILES): tinyboard-panel.pcb + pcb -x gerber tinyboard-panel.pcb fab: $(GERBER_FILES) @sh -c 'D=tinyboard-`date +\%Y\%m\%d-\%H\%M` && mkdir $$D && \ - cp tinyboard.top.gbr $$D/tinyboard.gtl && \ - cp tinyboard.bottom.gbr $$D/tinyboard.gbl && \ - cp tinyboard.topmask.gbr $$D/tinyboard.gts && \ - cp tinyboard.bottommask.gbr $$D/tinyboard.gbs && \ - cp tinyboard.topsilk.gbr $$D/tinyboard.gto && \ - cp tinyboard.bottomsilk.gbr $$D/tinyboard.gbo && \ - cp tinyboard.plated-drill.cnc $$D/tinyboard.txt && \ + cp tinyboard-panel.top.gbr $$D/tinyboard.gtl && \ + cp tinyboard-panel.bottom.gbr $$D/tinyboard.gbl && \ + cp tinyboard-panel.topmask.gbr $$D/tinyboard.gts && \ + cp tinyboard-panel.bottommask.gbr $$D/tinyboard.gbs && \ + cp tinyboard-panel.topsilk.gbr $$D/tinyboard.gto && \ + cp tinyboard-panel.bottomsilk.gbr $$D/tinyboard.gbo && \ + cp tinyboard-panel.plated-drill.cnc $$D/tinyboard.txt && \ zip -r $$D.zip $$D && \ echo "Done. Output in $$D.zip."; \ echo "You may also want to do git tag gerber-fab-$$D" ' diff --git a/panel.pl b/panel.pl new file mode 100644 index 0000000..d551e56 --- /dev/null +++ b/panel.pl @@ -0,0 +1,126 @@ +#!/usr/bin/perl +# -*- perl -*- + +# Copyright 2006 DJ Delorie +# Released under the terms of the GNU General Public License, version 2 + +sub baseboard { + my ($file, $width, $height, $nbase) = @_; + if (! $nbase) { + $base = $file; + $base =~ s@.*/@@; + } else { + $base = $nbase; + } + + $panelcopperlayers = ".*" unless $panelcopperlayers; + + $pscript = "$base.pscript"; + open(PS, ">$pscript"); + push(@files_to_remove, "$base.pscript"); + + open(S, $file) || die("$file: $!"); + $outname = "$base.panel.pcb"; + $outname =~ s/pnl\.panel\.pcb/pcb/; + open(O, ">$outname"); + while () { + if (/PCB\[.* (\S+) (\S+)\]/) { + s/ (\S+) (\S+)\]/ $width $height\]/; + } + s/Cursor\[.*\]/Cursor[0 0 0.0]/; + if (/^Flags/) { + s/,uniquename,/,/; + s/,uniquename//; + s/uniquename,//; + } + next if /\b(Via|Pin|Pad|ElementLine|Line|Arc|ElementArc|Text)/; + if (/Polygon|Element/) { + $hole = 0; + while () { + $hole++ if /Hole \(/; + last if /^\s*\)\s*$/ && $hole <= 0; + $hole-- if /\)/; + } + next; + } + if (/Layer/) { + if (@panelvias) { + print O @panelvias; + @panelvias = (); + } + } + print O; + if (/Layer\((\d+) \"(.*)\"\)/) { + $lnum = $1; + $lname = $2; + print O scalar ; + print STDERR "layer $lnum $lname vs '$panelcopperlayers'\n"; + if ($lnum =~ /$panelcopperlayers/ || $lname =~ /$panelcopperlayers/) { + print O @panelcopper; + } + } + } + close O; + close S; + + print PS "LoadFrom(Layout,$outname)\n"; + + $ox = $oy = 0; +} + +sub loadboard { + my ($file) = @_; + $seq = 1 + $seq; + + open(S, $file); + open(O, ">temp-panel.$seq"); + while () { + if (/PCB\[.* (\S+) (\S+)\]/) { + $width = &parseval($1); + $height = &parseval($2); + } + s/Cursor\[.*\]/Cursor[0 0 0.0]/; + print O; + } + close O; + close S; + print PS "LoadFrom(LayoutToBuffer,temp-panel.$seq)\n"; + push(@files_to_remove, "temp-panel.$seq"); +} + +sub opaste { + $vx = $ox; + $vy = $oy + $height; + print PS "PasteBuffer(ToLayout,$ox,$oy)\n"; + $ox += $width; + $oy = 0; +} + +sub vpaste { + print PS "PasteBuffer(ToLayout,$vx,$vy)\n"; + $vy += $height; +} + +sub done { + print PS "SaveTo(LayoutAs,$outname)\n"; + print PS "Quit()\n"; + + close PS; + + system "set -x; pcb --action-script $pscript"; + #system "pcb -x ps $base.panel.pcb"; + #unlink @files_to_remove; +} + +sub parseval { + my ($v) = @_; + if ($v =~ /mil/) { + $v *= 100; + } + if ($v =~ /mm/) { + $v *= 3937.007874015748; + } + return 0 + $v; +} + +1; diff --git a/panel2pcb b/panel2pcb new file mode 100755 index 0000000..b281dec --- /dev/null +++ b/panel2pcb @@ -0,0 +1,99 @@ +#!/usr/bin/perl +# -*- perl -*- + +# Copyright 2006 DJ Delorie +# Released under the terms of the GNU General Public License, version 2 + +if (! @ARGV) { + print "Usage: pcb2panel board1.pcb board2.pcb board3.pcb > boards.pcb"; + print "Then edit boards.pcb, putting each outline where you want it\n"; + print "and sizing the board. Then:\n"; + print "panel2pcb [-l regex] boards.pcb\n"; + print "and edit/print boards.panel.pcb\n"; + exit 0; +} + +$mydir = $0; +if ($mydir =~ m@/@) { + $mydir =~ s@[^/]*$@@; +} else { + $mydir = "."; +} + +require "$mydir/panel.pl"; + +$panel = shift; + +if ($panel eq "-l") { + $panelcopperlayers = shift; + $panel = shift; +} + +open(P, $panel); +while (

) { + if (/PCB\[.* (\S+) (\S+)\]/) { + $panel_width = &parseval($1); + $panel_height = &parseval($2); + } + if (/Element\[\"[^\"]*\" \"([^\"]*)\" \"([^\"]*)\" \"([^\"]*)\" (\S+) (\S+)/) { + $pcb = $1; + $base = $2; + $value = $3; + $mx = &parseval($4); + $my = &parseval($5); + %pinx = (); + %piny = (); + } + if (/Pin\[(\S+) (\S+) \S+ \S+ \S+ \S+ \"(\d)\"/) { + $pinx{$3} = &parseval($1); + $piny{$3} = &parseval($2); + } + if ($pcb && /\)/) { + if ($pinx{'1'} < $pinx{'2'}) { + $rot = 0; + } elsif ($pinx{'1'} > $pinx{'2'}) { + $rot = 2; + } elsif ($piny{'1'} < $piny{'2'}) { + $rot = 3; + } elsif ($piny{'1'} > $piny{'2'}) { + $rot = 1; + } + push (@paste, "$pcb\0$rot\0$mx\0$my"); + $pcb = undef; + } + if (/Via/) { + push (@panelvias, $_); + } + if (/^Layer\([^)]*\)$/) { + $junk =

; # The opening '(' + while ($junk =

) { + last if $junk =~ /^\)/; + push (@panelcopper, $junk); + } + } +} + +$tmp = "/tmp/panel$$.pcb"; + +$start = $paste[0]; +$start =~ s/\0.*//; + +$panel =~ s/\.pcb$//; +&baseboard($start, $panel_width, $panel_height, $panel); + +$lastboard = undef; +for $paste (sort @paste) { + ($pcb, $rot, $mx, $my) = split(/\0/, $paste); + if ($lastboard ne $pcb) { + &loadboard ($pcb); + $lastboard = $pcb; + $lastrot = 0; + } + while ($lastrot != $rot) { + print PS "PasteBuffer(Rotate,1)\n"; + $lastrot = ($lastrot+1) % 4; + } + print PS "PasteBuffer(ToLayout,$mx,$my)\n"; +} + +&done(); diff --git a/pcb2panel b/pcb2panel new file mode 100755 index 0000000..ddc7bbf --- /dev/null +++ b/pcb2panel @@ -0,0 +1,101 @@ +#!/usr/bin/perl +# -*- perl -*- + +# Copyright 2006 DJ Delorie +# Released under the terms of the GNU General Public License, version 2 + +$mydir = $0; +if ($mydir =~ m@/@) { + $mydir =~ s@[^/]*$@@; +} else { + $mydir = "."; +} + +require "$mydir/panel.pl"; + +if (! @ARGV) { + print "Usage: pcb2panel board1.pcb board2.pcb board3.pcb > boards.pcb\n"; + print "Then edit boards.pcb, putting each outline where you want it\n"; + print "and sizing the board. Then:\n"; + print "panel2pcb boards.pcb\n"; + print "and edit/print boards.panel.pcb\n"; + exit 0; +} + +for $pcb (@ARGV) { + $base = $pcb; + $base =~ s@.*/@@; + $base =~ s@\.pcb$@@; + $base{$pcb} = $base; + push (@pcbs, $pcb); + open(PCB, $pcb); + while () { + if (/^PCB\[".*" (\S+) (\S+)\]/) { + $width{$pcb} = &parseval($1); + $height{$pcb} = &parseval($2); + printf STDERR "%s : %d x %d\n", $pcb, $width{$pcb}, $height{$pcb}; + last; + } + } + $outline = ''; + while () { + if (/Layer\(.*"outline"\)/) { + $junk = ; # open paren + while () { + last if /^\)/; # close paren + ($args) = m@\[(.*)\]@; + ($x1, $y1, $x2, $y2, $width) = split(' ', $args); + $outline .= " ElementLine[$x1 $y1 $x2 $y2 $width]\n"; + } + } + } + push (@outlines, $outline); + close PCB; +} + +$pw = 10000; +$ph = 0; +for $pcb (@pcbs) { + $pw += 10000; + $pw += $width{$pcb}; + $ph = $height{$pcb} if $ph < $height{$pcb}; +} +$ph += 20000; + +print "PCB[\"\" $pw $ph]\n"; +print "Grid[10000.0 0 0 1]\n"; +print "DRC[799 799 800 100 1500 800]\n"; +print "Groups(\"1,c:2,s\")\n"; #" + +$x = 10000; +$y = 10000; +for ($i=0; $i<@pcbs; $i++) { + $pcb = $pcbs[$i]; + $outline = $outlines[$i]; + $desc = $pcb; + $name = $base{$pcb}; + $value = "$width{$pcb} x $height{$pcb}"; + $w = $width{$pcb}; + $h = $height{$pcb}; + + print "Element[\"\" \"$desc\" \"$name\" \"$value\" $x $y 2000 2000 0 50 \"\"] (\n"; + print " Pin[0 0 1000 0 0 400 \"1\" \"1\" \"\"]\n"; + print " Pin[$w 0 1000 0 0 400 \"2\" \"2\" \"\"]\n"; + if ($outline =~ /\S/) { + print $outline; + } else { + print " ElementLine[0 0 $w 0 100]\n"; + print " ElementLine[0 0 0 $h 100]\n"; + print " ElementLine[$w 0 $w $h 100]\n"; + print " ElementLine[0 $h $w $h 100]\n"; + } + print ")\n"; + $x += $w + 10000; +} + +print "Layer(1 \"component\")()\n"; +print "Layer(2 \"solder\")()\n"; +print "Layer(3 \"silk\")()\n"; +print "Layer(4 \"silk\")()\n"; + +exit 0; -- 2.39.3