#!/usr/bin/perl # convert GERBER file and aperture table to Fig # Andrew Daviel TRIUMF Feb 2002 advax@triumf.ca unless ($ARGV[0]) { &usage ; exit ; } # big grid 1" = 1200 pt, 0.5" 600, 0.25 300 , 0.125 150, 0.0625 75 # metric 1cm = 900 5mm 450 ... 45 # type text = 4 # justification 0 left 1 center 2 right # colour 0 black 4 red 1 blue # type justif colour depth ? font size angle flags zz x y text # print "4 $just $colour $depth 0 $fn $pt $angle $flags 210 750 $x $y $_\\001\n" ; # type poly = 2 # type x styl x fgcol bgcol depth x fil angle x cap x x fwdarw backarw npts # 2 1 0 1 4 7 50 0 -1 0.000 0 0 -1 0 0 3 # line width 1 0.012" = 10 units $lw2 = 10/2 ; # half linewidth $fg = 4 ; $bg = 4 ; $angle = 0.0 ; $date = localtime() ; # circle rad # 1 x sty wid fg bg dep x fil angle x x X Y R R X Y # 1 3 0 4 0 7 50 0 -1 0.000 1 0.0000 825 1350 618 618 825 1350 1425 1200 # 1 3 0 4 0 7 50 0 -1 0.000 1 0.0000 825 1350 618 618 825 1350 1425 1200 # fil #1 3 0 4 0 -1 50 0 4 0.000 1 0.0000 1575 2250 586 586 1575 2250 2161 2250 #1 3 0 4 0 -1 50 0 4 0.000 1 0.0000 1575 2250 586 586 1575 2250 2161 2250 # 100% fill #1 3 0 4 0 -1 50 0 20 0.000 1 0.0000 1575 2250 586 586 1575 2250 2161 2250 # 50% fill #1 3 0 4 0 -1 50 0 10 0.000 1 0.0000 1575 2250 586 586 1575 2250 2161 225 # pattern fill #1 3 0 4 0 7 50 0 44 0.000 1 0.0000 1875 2025 636 636 1875 2025 2511 2025 # gap angle #1 3 3 4 0 7 50 0 41 7.500 1 0.2269 1875 2025 636 636 1875 2025 2511 2025 #1 3 3 4 0 7 50 0 41 7.500 1 0.2269 1875 2025 636 636 1875 2025 2511 2025 # circle dia #1 4 0 4 0 7 50 0 -1 0.000 1 0.0000 1725 1537 457 457 1350 1800 2100 1275 # ellipse radii # x x x wid x x dep x x x x X y xr yr # 1 1 0 4 0 7 50 0 -1 0.000 1 0.0000 1050 1575 825 300 1050 1575 1875 1275 # 1 1 0 4 0 7 50 0 -1 0.000 1 0.0000 1050 1575 825 300 1050 1575 1875 1275 # ellipse dia #x x x x x x dep x x x x x X Y XR YR #1 2 0 4 0 7 50 0 -1 0.000 1 0.0000 2175 1837 675 263 1500 2100 2850 1575 #1 2 0 4 0 7 50 0 -1 0.000 1 0.0000 2175 1837 675 263 1500 2100 2850 1575 # box # wid dep #2 2 0 4 0 7 50 0 -1 0.000 0 0 -1 0 0 5 # X1 Y1 X2 Y1 X2 Y2 X1 Y2 X1 Y1 # 1500 2250 2625 2250 2625 1725 1500 1725 1500 2250 #c Gerber Meaning HP meaning #c D01 aperture open PD pen down #c D02 aperture close PU pen up #c D03 flash CI draw circle #c Pnn select aperture SPnn select pen #c Cnnn select aperture - calculate circle size for CI #c G54 initialize IN initialize #c M02 end of file SP0,NR park pen, deselect plotter $depth = 50 ; $width = 1 ; if ($ARGV[2]) { $depth = $ARGV[2] ; if ($depth <20) { $fg = $bg = $depth ; } } open (OUT,">$ARGV[1]") ; print OUT<) ; unless (/^G54\*/) { print STDERR "$ARGV[0] not a Gerber file; missing G54*" ; } while () { tr/ \r\n//d ; if (/^G54/) { print "Init\n" ; s/G54// ; } #D10* #X00190Y00100D02*D03* #D21* #X-00050Y00400D02* #M02* #P3* #X01505Y01583D01* #X01577Y01655D01* #C50* #D03* #Y4600D02* $pixel = 1200 ; s/^%%/%/ ; print "$_\n" ; #print OUT "# $_\n" ; if (/^%FS(.)(.)X([\d])([\d])Y([\d])([\d])/) { print "Format $1 $2 x $3.$4 y $5.$6\n" ; } elsif (/^%AD(D[\d]+)([CR]),([\d\.]+)X([\d\.]+)X([\d\.]+)/) { print "Unknown aperture $_\n" ; } elsif (/^%AD(D[\d]+)([CR]),([\d\.]+)X([\d\.]+)/) { $size{$1} = $3 ; $size2{$1} = $4 ; if ($2 eq 'C') { print "$1 DONUT $3 $3 $4 FLASH\n" ; } elsif ($2 eq 'R') { $type{$1} = 'RECTANGULAR' ; print "$1 RECTANGULAR $3 $4 0.00 FLASH\n" ; } else { print "Unknown aperture $_\n" ; } } elsif (/^%AD(D[\d]+)([CR]),([\d\.]+)/) { $size{$1} = $3 ; $size2{$1} = $3 ; $type{$1} = 'R' ; print "$1 $type{$2} $3 $3 0.00 FLASH\n" ; } elsif (/^G04/ || /^%G04/) { print "$_\n" ; # comment print OUT "# $_\n" ; # comment } elsif (/^D03\*/) { # if (@line) { &doline ; } &doflash ; } elsif (/^D02\*/) { print "move $x $y\n" ; if (@line) { &doline ; } $open = 0 ; } elsif (/^(D[\d]+)\*/) { if (@line) { &doline ; } unless ($type{$1} && $size{$1}) { print "ERROR no aperture $1\n" ; } print "aperture $1 size $size{$1} x $size2{$1} type $type{$1}\n" ; $radius = int($size{$1}*$pixel/2 + 0.5) - $lw2 ; $radius2 = int($size2{$1}*$pixel/2 + 0.5) - $lw2 ; unless ($radius2) { $radius2 = $radius ; } $diam = int($size{$1}*$pixel+ 0.5) ; $type = $type{$1} ; $width = int($diam/12+0.5) ; if ($width < 1) { $width = 1 ; } } elsif (/^(P[\d]+)\*/) { if (@line) { &doline ; } print "pen $1\n" ; } elsif (/^M02\*/) { if (@line) { &doline ; } print "End\n" ; } elsif (/^(C[\d]+)\*/) { if (@line) { &doline ; } print "circle$1\n" ; } elsif (/^X(-*[\d]+)Y(-*[\d]+)D01\*/) { $x = int($2*$pixel/1000+0.5) ; $y = int($1*$pixel/1000+0.5) ; print "x $1 y $2 draw $x $y\n" ; $open = 1 ; if ($x ne '' && $y ne '') { push (@line,"$x $y") ; } } elsif (/^X(-*[\d]+)D01\*/) { $open = 1 ; $y = int($1*$pixel/1000+0.5) ; print "x $1 draw $x $y\n" ; if ($x ne '' && $y ne '') { push (@line,"$x $y") ; } } elsif (/^Y(-*[\d]+)D01\*/) { $open = 1 ; $x = int($1*$pixel/1000+0.5) ; print "y $1 draw $x $y\n" ; if ($x ne '' && $y ne '') { push (@line,"$x $y") ; } } elsif (/^X(-*[\d]+)Y(-*[\d]+)D02\*/) { if (@line) { &doline ; } $open = 0 ; $x = int($2*$pixel/1000+0.5) ; $y = int($1*$pixel/1000+0.5) ; print "x $1 y $2 move $x $y\n" ; if ($x ne '' && $y ne '') { push (@line,"$x $y") ; } } elsif (/X(-*[\d]+)Y(-*[\d]+)D03\*/) { if (@line) { &doline ; } $x = int($2*$pixel/1000+0.5) ; $y = int($1*$pixel/1000+0.5) ; &doflash ; } elsif (/^Y(-*[\d]+)D02\*/) { if (@line) { &doline ; } $open = 0 ; $x = int($1*$pixel/1000+0.5) ; print " y $1 move $x $y\n" ; if ($x ne '' && $y ne '') { push (@line,"$x $y") ; } } elsif (/^X(-*[\d]+)D03\*/) { if (@line) { &doline ; } $y = int($1*$pixel/1000+0.5) ; &doflash ; } elsif (/^Y(-*[\d]+)D03\*/) { if (@line) { &doline ; } $x = int($1*$pixel/1000+0.5) ; &doflash ; } elsif (/^X(-*[\d]+)D02\*/) { if (@line) { &doline ; } $open = 0 ; $y = int($1*$pixel/1000+0.5) ; print "x $1 move $x $y\n" ; if ($x ne '' && $y ne '') { push (@line,"$x $y") ; } } else { if (@line) { &doline ; } if ($_) { print "error $_\n" ; } } } sub doline { my $npts = @line ; my $line ; unless ($open) { print "doline closed\n" ; undef(@line) ; return ; } print "doline $npts points x0 $x0 y0 $y0\n" ; foreach $line (@line) { print "\t$line\n" ; } if ($npts > 1) { # unless ($type eq 'D') { print "error draw $type\n" ; } print OUT "2 1 0 $width $fg $bg $depth 0 -1 $angle 0 1 -1 0 0 $npts\n" ; foreach $line (@line) { print OUT "\t$line\n" ; } } else { print OUT "2 1 0 $width $fg $bg $depth 0 -1 $angle 0 1 -1 0 0 2\n" ; print OUT "\t$x0 $y0\n" ; foreach $line (@line) { print OUT "\t$line\n" ; } } undef(@line) ; $x0 = $x ; $y0 = $y ; } sub usage { print STDERR< (default 50) Round flash are translated to filled circles, square flash to filled boxes and lines to round-end polylines. EOT } sub doflash { print "flash $type\n" ; if ($type eq 'R') { print OUT "1 3 0 1 0 0 $depth 0 20 0.000 1 0.0000 $x $y $radius $radius $x $y 0 0\n" ; } elsif ($type eq 'S' || $type eq 'RECTANGULAR') { print "flash $radius2 x $radius\n" ; $x1 = $x - $radius2 ; $x2 = $x + $radius2 ; $y1 = $y - $radius ; $y2 = $y + $radius ; print OUT "2 2 0 1 0 0 $depth 0 20 0.000 0 0 -1 0 0 5\n" ; print OUT "\t$x1 $y1 $x2 $y1 $x2 $y2 $x1 $y2 $x1 $y1\n" ; } else { print "error flash type $type\n" ; } }