#!/usr/bin/perl -w

#### TODO:
# do courtyard, paste mask

use strict;
use utf8;
use Data::Dumper;
use Encode;
use lib '.';

binmode(STDOUT, ":encoding(UTF-8)");
binmode(STDERR, ":encoding(UTF-8)");

# Note pcb coordinate system:
#    -y
# -x  0  +x
#    +y
# angle 0 => left, 90 down, 180 right, 270 up

# Angles
#   X   y   atan  pcb anble
#   1   0   0     180
#   1   1   45    180-45
#   0   1   90    180-90
#   -1  1   90+45 45
#   -1  0   180   0
# i.e. pcb angle = 180 - atan() (using degrees)


########################################

my %minimum = (
    thermal_to_pad_distance => 0.2, # some says 0.25
    solder_mask_width => 0.1, # ??
);

########################################
# possible todos
# http://www.kemet.com/Lists/TechnicalArticles/Attachments/29/f2100e.pdf

########################################
# footprint.pm:
#use "footprint.pm";

########################################
########################################
########################################
# Global variables
# (there a few dsub specific in the dsub section)

my $debug = 0;
my $pi = 2 * atan2(1,0);
my $s2 = sqrt(2);
my $u = undef;

my $TOE  = 0;
my $HEEL = 1;
my $SIDE = 2;
my $ROUNDOFF = 3;
my $COURTYARD = 4;
# theese are how much to enlarge given dimesions to get the pad size
#                 toe   heel  side roundoff courtyard_excess
# for pitch >= 0.625, L as in Large
my @non_ipc   = ( 0.00, 0.00, 0.00, 0.00, 0.00 ); # pad with dimesions given
my @ipc_gw_LA = ( 0.55, 0.45, 0.05, 0.05, 0.50 );
my @ipc_gw_LB = ( 0.35, 0.35, 0.03, 0.05, 0.25 );
my @ipc_gw_LC = ( 0.15, 0.25, 0.01, 0.05, 0.10 );

# for pitch < 0.625, S as in Small
my @ipc_gw_SA = ( 0.55, 0.45, 0.01, 0.05, 0.50 );
my @ipc_gw_SB = ( 0.35, 0.35,-0.02, 0.05, 0.25 );
my @ipc_gw_SC = ( 0.15, 0.25,-0.04, 0.05, 0.10 );
my @ipc_hdr = ( "", "_A", "_B", "_C" );
my %ipc = (
    "S" => [ \@non_ipc, \@ipc_gw_SA, \@ipc_gw_SB, \@ipc_gw_SC, ],
    "L" => [ \@non_ipc, \@ipc_gw_LA, \@ipc_gw_LB, \@ipc_gw_LC, ],
);
my @radi = ("", "r");

sub ipc_get_cl($$$@) {
  my $max_width = shift;
  my $min_width = shift;
  my $max_toe_length = shift;
  my @tbl = @_;

  my $xmax = $max_width/2 + $tbl[$TOE];
  my $xmin = $min_width/2 - $max_toe_length - $tbl[$HEEL];
  my $xcenter = ( $xmax + $xmin ) / 2;
  my $xlen = $xmax - $xmin;
  ($xcenter, $xlen);
}

# from http://pcbdesignandfab.com/guidelines.htm
my @drill_chart = ( # drill bit to inches
    .0000, .2280, .2210, .2130, .2090,  .2055, .2040, .2010, .1990, .1960,
    .1935, .1910, .1890, .1850, .1820,  .1800, .1770, .1730, .1695, .1660,
    .1610, .1590, .1570, .1540, .1520,  .1495, .1470, .1440, .1405, .1360,
    .1285, .1200, .1160, .1130, .1110,  .1100, .1065, .1040, .1015, .0995,
    .0980, .0960, .0935, .0890, .0860,  .0820, .0810, .0785, .0760, .0730,
    .0700, .0670, .0635, .0595, .0550,  .0520, .0465, .1250, .0420, .0410,
    .0400, .0390, .0380, .0370, .0360,  .0350, .0330, .0320, .0310, .0292,
    .0280, .0260, .0250, .0240, .0225,  .0210, .0000, .0180, .0160, .0145,
    .0135
);
my %awg_chart = ( # awg size to inches
    "4/0"=> 0.4600, "3/0"=> 0.4096, "2/0"=> 0.3648, "1/0"=> 0.3249,
     "1" => 0.2893,  "2" => 0.2576,  "3" => 0.2294,  "4" => 0.2043,  "5" => 0.1819,
     "6" => 0.1620,  "7" => 0.1443,  "8" => 0.1285,  "9" => 0.1144, "10" => 0.1019,
    "11" => 0.0907, "12" => 0.0808, "13" => 0.0720, "14" => 0.0641, "15" => 0.0571,
    "16" => 0.0508, "17" => 0.0453, "18" => 0.0403, "19" => 0.0359, "20" => 0.0320,
    "21" => 0.0285, "22" => 0.0253, "23" => 0.0226, "24" => 0.0201, "25" => 0.0179,
    "26" => 0.0159, "27" => 0.0142, "28" => 0.0126, "29" => 0.0113, "30" => 0.0100,
    "31" => 0.0089, "32" => 0.0080, "33" => 0.0071, "34" => 0.0063, "35" => 0.0056,
    "36" => 0.0050, "37" => 0.0045, "38" => 0.0040, "39" => 0.0035, "40" => 0.0031,
    "41" => 0.0028, "42" => 0.0025, "43" => 0.0022, "44" => 0.0020,
);

# p3 http://www.yageo.com/pdf/Product Selection Guide 2009.pdf
# https://en.wikipedia.org/wiki/Surface_mount
# and other places
my @chip_sizes = (
    #  mm    mil
    [ "0201", "008004" ],
    [ "03015", "009005" ],
    [ "0402", "01005" ],
    [ "0603", "0201" ],
    [ "0605", "0202" ],
    [ "0816", "0306" ],
    [ "1005", "0402" ],
    [ "1010", "0404" ],
    [ "1013", "0405" ],
    [ "1020", "0408" ],
    [ "1220", "0508" ],
    [ "1310", "0504" ],
    [ "1608", "0603" ],
    [ "1616", "0606" ],
    [ "1632", "0612" ],
    [ "1640", "0616" ],
    [ "2012", "0805" ],
    [ "2520", "1008" ],
    [ "3216", "1206" ],
    [ "3225", "1210" ],
    [ "3245", "1218" ],
    [ "3250", "1224" ],
    [ "3264", "1225" ],
    [ "3625", "1410" ],
    [ "4516", "1806" ],
    [ "4520", "1808" ],
    [ "4532", "1812" ],
    [ "4564", "1825" ],
    [ "5025", "2010" ],
    [ "5320", "2007" ],
    [ "5750", "2220" ],
    [ "6332", "2512" ], # ipc 782, can be a misspelling
    [ "6432", "2512" ],
    [ "7451", "2920" ],
    [ "7836", "3014" ],
);
my %chip_mil2mm;
sub chip_mil2mm($) {
    my $mil = shift;
    my $mm = $chip_mil2mm{$mil};
    if (!defined($mm)) {
	for my $r (@chip_sizes) {
	    $chip_mil2mm{$$r[1]} = $$r[0];
	}
	$mm = $chip_mil2mm{$mil};
    }
    $mm;
}

# http://www.pcb-3d.com/tutorials/how-to-calculate-pth-hole-and-pad-diameter-sizes-according-to-ipc-7251-ipc-2222-and-ipc-2221-standards/
# https://blogs.mentor.com/tom-hausherr/blog/tag/padstacks/
my %IPC_2222_min_drill     = ( 'A' => 0.25, 'B' => 0.20, 'C' => 0.15 ); # lead dia + this value = minimum hole diameter
my %IPC_2221_min_thickness = ( 'A' => 0.70, 'B' => 0.60, 'C' => 0.50 ); # hole dia + this value = min. thickness or pad dia.

# theese are similar to IPC's level A, B, C, but with values derived from footprints at cvs.gedasymbols.org
# to not to be confused with IPC level A B C (one could use numbers instead of letters)
my $thickness_as_digit = 0;
my @thickness_suffix = qw/ a b c d e x /; # a = thinnest annulus, e = thickest, x is for the physical maximum annulus
my @drill2thickness = (
    # data from cvs.gedasymbols in comments
    #"min" [ 0.2662, 1.0966 ],
    [ 0.50, 1.10 ], # size a
    #"mid" [ 0.6041, 1.3211 ],
    [ 0.60, 1.32 ], # size b
    #"mpe" [ 0.7195, 1.5476 ],
    [ 0.70, 1.55 ], # size c
    [ 1.35, 1.63 ], # size d, halfvay between size c and e
    #"max" [ 2.0090, 1.7107 ],
    [ 2.00, 1.71 ], # size e
);
my %drill2thickness; # cache

my $clearance = 0.5;
my $mask_gap_default = 0.2;
my $mask_gap  = $mask_gap_default;
my $pin_no = 0;
my $round_first_pin = 0;
my $pad_as_outline = 0; # instead of pads, draw element_lines as an outline
my $silk_width = 0;
my $silk_w = 0;
my $origin = [ 0, 0 ];

my $bbx1;
my $bbx2;
my $bby1;
my $bby2;
my @bounding_box; # arr of [ $xmin, $xmax, $ymin, $ymax, $pin_no, $bbr ] for each pad and pin

my $pr_ix = 0;
my $pr_pfx = '';
my $pr_h;
my $pr_save = "";

# the width and starting position for the next silk line (ElementLine)
my $silk_default = 0.32;
my $silk_x = 0;
my $silk_y = 0;
my $silk_xmm; # = mk_mm($silk_x);
my $silk_ymm; # = mk_mm($silk_y);
my $silk_count = 0;

########################################
########################################
########################################

sub pr_inc() {
  $pr_ix++;
  $pr_pfx .= "  ";
}
sub pr_dec() {
  if ($pr_ix > 0) {
    $pr_ix--;
    $pr_pfx = substr($pr_pfx, 0, -2);
  }
}

sub pr(;$$) {
  my $str = shift;
  my $flg = shift;
  if ($pr_h) {
      if ($flg) {
	  print $pr_h $str;
      } else {
	  print $pr_h $pr_pfx, $str;
      }
  }
  $pr_save .= sprintf "%s%s", $pr_pfx, $str;
}

sub str_trim($) {
    my $str = shift;
    $str =~ tr/ \t\r\n/ /s;
    $str =~ s/ $//;
    $str =~ s/^ //;
    $str;
}

sub mk_mm($) {
  my $val = shift;
  sprintf "%7.3fmm", $val;
}
sub rm_mm( $ ) {
    my $val = shift;
    $val =~ s/mm$//;
    $val;
}

sub element_start($;$$$$) {
  my $file  = shift;
  my $str   = shift // ""; # whatever text you want after the opening Element[] line
  my $desc  = shift // ""; # general description of a group of components/parts
  my $name  = shift // "M?"; # the refdes
  my $val = $file;
  $val =~ s/\.fp//;
  my $value = shift // $val; # value or part number, sometimes equal to file name minus ".fp"

  my $pfx = "";
  if ($file !~ m/^>/) { $pfx = ">"; }
  open($pr_h, $pfx . $file) || return;

  # the refdes text is always just above origo
  pr "\nElement [\"\" \"$desc\" \"$name\" \"$value\"  0 0 -0.7mm -2mm 0 100 \"\"]\n(\n";
  if ($str) { pr $str; }
  pr_inc;
  bb_clear();
  $pin_no = 0;
}
sub element_stop(;$) {
  my $extra = shift;
  pr_dec;
  pr ")\n";
  if ($extra) {
      pr "\n";
      pr $extra;
  }
  close $pr_h;
  $pr_h = undef;
}
sub attribute($$) {
    my $Name  = shift;
    my $Value = shift;
    pr "Attribute (\"$Name\" \"$Value\")\n";
}

sub inc_pin_no() {
  $pin_no++;
}
sub use_same_pin_no() {
  $pin_no--;
}

sub ipc_corner($) {
    # per IPC-7351C according to
    # http://www.ocipcdc.org/archive/What_is_New_in_IPC-7351C_03_11_2015.pdf
    # http://www.pce-oc.org/archive/What_is_New_in_IPC-7351C_03_11_2015.pdf
    my $w = shift; # smallest pad width

    my $r = 0.25 * $w;
    $r = round($r, 0.01);
    if ($r > 0.25) { $r = 0.25; }

    $r;
}
sub pad($$$$ ; $$$$$) {
  my $x = shift; # pad center
  my $y = shift; # pad center
  my $px = shift;
  my $py = shift;

  my $name = shift;
  my $popt = shift;
  my $r = shift;
  my $pad_number = shift;
  my $rotation = shift // 0;
  # no inclined pads for the moment

  if (!defined($popt)) { $popt = ""; }
  if (!defined($r)) { $r = 0; }
  if (defined($pad_number)) {
      $pin_no = $pad_number;
  } else {
      $pin_no++;
  }
  if (!defined($name)) { $name = $pin_no; }
  #print "$x, $y, $px, $py / $name, $popt, $r, $pad_number\n";

  my $x1;
  my $x2;
  my $y1;
  my $y2;
  my $w;
  my $clr = mk_mm($clearance);
  my $msk;

  if ($pad_as_outline) {
      silk_rect([$x - $px/2, $y - $py/2], [$x + $px/2,$y + $py/2], $r);
  } else {
      my $sqopt = "";
      my $rr = 0;
      my $l;
      my $is_vert = 0;
      if ($px < $py) {
	  $is_vert = 1;
	  $l = ($py - $px)/2;
	  $x1 = $x;
	  $x2 = $x;
	  $y1 = $y - $l;
	  $y2 = $y + $l;
	  $w  = $px - 2*$r;
	  $rr = $px/2;
	  $msk = $px + 2*$mask_gap;
	  #print "Taller: $px $py $r $w\n";
      } else {
	  my $l = ($px - $py)/2;
	  $x1 = $x - $l;
	  $x2 = $x + $l;
	  $y1 = $y;
	  $y2 = $y;
	  $w  = $py - 2*$r;
	  $rr = $py/2;
	  $msk = $py + 2*$mask_gap;
	  #print "Wider: $px $py $r $w\n";
      }
      if ($r < 0 || $rr < $r) { $r = 0; }
      if ($r == 0) {
	  $sqopt = "square";
	  if ($popt) { $sqopt = $popt . ",square"; }
      }
      if ($r >= $rr) { $w = 2*$rr; }
      $x1 = mk_mm($x1);
      $x2 = mk_mm($x2);
      $y1 = mk_mm($y1);
      $y2 = mk_mm($y2);
      $w  = mk_mm($w);
      $msk = mk_mm($msk);
      pr "Pad [ $x1 $y1  $x2 $y2  $w $clr $msk \"$name\" \"$pin_no\" \"$sqopt\" ]\n";

      if ($r) {
	  $x1 = mk_mm($x - $px/2 + $r);
	  $x2 = mk_mm($x + $px/2 - $r);
	  $y1 = mk_mm($y - $py/2 + $r);
	  $y2 = mk_mm($y + $py/2 - $r);
	  $w  = mk_mm(2*$r);
	  $msk = mk_mm(2*$r + 2*$mask_gap);
	  pr "Pad [ $x1 $y1  $x2 $y1  $w $clr $msk \"$name\" \"$pin_no\" \"$popt\" ]\n";
	  pr "Pad [ $x1 $y2  $x2 $y2  $w $clr $msk \"$name\" \"$pin_no\" \"$popt\" ]\n";
	  pr "Pad [ $x1 $y1  $x1 $y2  $w $clr $msk \"$name\" \"$pin_no\" \"$popt\" ]\n";
	  pr "Pad [ $x2 $y1  $x2 $y2  $w $clr $msk \"$name\" \"$pin_no\" \"$popt\" ]\n";
      }
  }
  # redefine x1... to match bbx1...
  $x1 = $x - $px/2 - $mask_gap;
  $x2 = $x + $px/2 + $mask_gap;
  $y1 = $y - $py/2 - $mask_gap;
  $y2 = $y + $py/2 + $mask_gap;
  if ($r) { $r += $mask_gap; }
  push @bounding_box, [ $x1, $x2, $y1, $y2, $pin_no, $r ];
  if (!defined($bbx1)) {
      $bbx1 = $x1;
      $bbx2 = $x2;
      $bby1 = $y1;
      $bby2 = $y2;
  } else {
      if ( $x1 < $bbx1 ) { $bbx1 = $x1; }
      if ( $x2 > $bbx2 ) { $bbx2 = $x2; }
      if ( $y1 < $bby1 ) { $bby1 = $y1; }
      if ( $y2 > $bby2 ) { $bby2 = $y2; }
  }
}

sub pin( $$$$ ; $$$ ) {
  my $x   = shift; # pad center
  my $y   = shift; # pad center
  my $hole = shift;
  my $d_cu = shift;

  my $name = shift;
  my $popt = shift;
  my $pin_number = shift;

  my $xm = mk_mm($x);
  my $ym = mk_mm($y);
  my $mask = mk_mm( $d_cu + 2*$mask_gap );
  my $dm = mk_mm($d_cu);
  $hole = mk_mm($hole);
  my $opt = '';
  my $c = mk_mm($clearance);

  if (defined($pin_number)) {
        $pin_no = $pin_number;
  } else {
      $pin_no++;
  }
  my $bbr = $d_cu/2 + $mask_gap;
  if (!defined($name)) { $name = $pin_no; }
  if ($pin_no eq "1" && !$round_first_pin ) {
      $opt = "square";
      $bbr = 0;
  }
  if (defined($popt) && $popt ne "") { $opt = ($opt ne "" ? "$opt," : "") . $popt; }
  pr "Pin [ $xm $ym  $dm $c $mask $hole \"$name\" \"$pin_no\" \"$opt\" ]\n";

  my $x1 = $x - $d_cu/2 - $mask_gap;
  my $x2 = $x + $d_cu/2 + $mask_gap;
  my $y1 = $y - $d_cu/2 - $mask_gap;
  my $y2 = $y + $d_cu/2 + $mask_gap;
  push @bounding_box, [ $x1, $x2, $y1, $y2, $pin_no, $bbr ];
  if (!defined($bbx1)) {
      $bbx1 = $x1;
      $bbx2 = $x2;
      $bby1 = $y1;
      $bby2 = $y2;
  } else {
      if ( $x1 < $bbx1 ) { $bbx1 = $x1; }
      if ( $x2 > $bbx2 ) { $bbx2 = $x2; }
      if ( $y1 < $bby1 ) { $bby1 = $y1; }
      if ( $y2 > $bby2 ) { $bby2 = $y2; }
  }
}

########################################

sub inch_to_mm($) {
    my $inch = shift;
    25.4 * $inch;
}

sub mil_to_mm($) {
    my $mil = shift;
    my $res = undef;

    if (defined($mil)) {
	my $inch = $mil / 1000;
	$res = 25.4 * $inch;
    }
    $res;
}

sub sortNumbers(@) {
    sort { $a <=> $b } @_;
}

sub angleCompass2pcb($) {
    my $angle = shift;
    my $a = 270 - $angle;
    #if ($a < 0) { $a += 360; }
    $a;
}

sub round($;$) {
    my $val = shift;
    my $steps = shift // 1;

    if ($steps == 0) { return $val; }
    my $round = $steps * int( $val / $steps + 0.5 );
}
sub rounddown($$) {
    my $val = shift;
    my $steps = shift;

    if ($steps == 0) { return $val; }
    my $round = $steps * int( $val / $steps );
    if ($round > $val) { $round -= $steps; }

    $round;
}
sub roundup($$) {
    my $val = shift;
    my $steps = shift;

    if ($steps == 0) { return $val; }
    my $round = $steps * int( $val / $steps );
    if ($round < $val) { $round += $steps; }

    $round;
}

my @sweep = ( # TODO: better name
    #"cos" "sin" angle
    [ -1,  0 ], # 0°
    [ -1,  1 ], # 45°
    [  0,  1 ], # 90°
    [  1,  1 ],
    [  1,  0 ], # 180°
    [  1, -1 ],
    [  0, -1 ], # 270° or -90°
    [ -1, -1 ],
);

sub acos($) { # not in perl, have to add it
    my $x = shift;
    atan2( sqrt(1 - $x * $x), $x );
}

sub asin($) { # not in perl, have to add it
    my $x = shift;
    atan2(  $x, sqrt(1 - $x * $x) );
}

sub tan($) { # not in perl, have to add it
    my $x = shift;
    sin($x) / cos($x);
}

sub rad_deg($) { # conversion from radians to degrees (360° = one full turn)
    my $x = shift;
    180 * $x / $pi;
}

sub deg_rad($) { # conversino from degrees to radians
    my $x = shift;
    $x * $pi / 180;
}
sub Acos($) {
    my $x = shift;
    rad_deg(acos($x));
}
sub Asin($) {
    my $x = shift;
    rad_deg(asin($x));
}
sub Atan2($$) {
    my $y = shift;
    my $x = shift;
    rad_deg(atan2($y,$x));
}
sub PcbAngleV(@) {
    my @pos = @_;
    my @arr;
    for my $pos (@pos) {
	my ($x,$y) = @$pos;
	push @arr, PcbAngle($x, $y);
    }
    @arr;
}
sub PcbAnglev($) {
    my $pos = shift;
    my ($x,$y) = @$pos;
    PcbAngle($x, $y);
}
sub PcbAngle($$) {
    my $x = shift;
    my $y = shift;
    deg_normalize(Atan2($y, -$x));
}
#sub PcbAngle_test() {
#    my @arr = ( [-1,0], [-1,1], [0,1], [1,1], [1,0], [1,-1], [0,-1], [-1,-1] );
#    for my $rr (@arr) {
#	my ($x, $y) = @$rr;
#	my $a = PcbAngle($x, $y);
#	printf "(%5.2f, %5.2f) => %7.2f\n", $x, $y, $a;
#    }
#}
sub Sin($) {
    my $x = shift;
    sin(deg_rad($x));
}
sub Cos($) {
    my $x = shift;
    cos(deg_rad($x));
}
sub Tan($) {
    my $x = shift;
    tan(deg_rad($x));
}
sub deg_normalize($) { # 0 <= angle < 360
    my $da = shift;
    while ($da >= 360) { $da -= 360; }
    while ($da <    0) { $da += 360; }
    $da;
}
sub rad_normalize1($) { # normalize angle, -$pi < angle <= $pi
    my $da = shift;
    while ($da >   $pi) { $da -= 2*$pi; }
    while ($da <= -$pi) { $da += 2*$pi; }
    $da;
}

sub rad_normalize2($) { # normalize angle, 0 <= angle < 2*$pi
    my $da = shift;
    while ($da >= 2*$pi) { $da -= 2*$pi; }
    while ($da <  0    ) { $da += 2*$pi; }
    $da;
}

sub triangle_x($$) {
    my $r = shift;
    my $y = shift;
    my $x = sqrt( $r*$r - $y*$y );
    $x;
}
sub triangle_r($$) {
    my $x = shift;
    my $y = shift;
    my $r = sqrt( $x*$x + $y*$y );
    $r;
}

# circle segment: $r circle radius, $h segment height, $s segment length
sub circle_segment_h($$) {
    my $r = shift;
    my $s = shift;
    my $h = $r - sqrt( $r*$r - $s*$s/4 );
}
sub circle_segment_s($$) {
    my $r = shift;
    my $h = shift;
    my $s = 2 * sqrt( $h*(2*$r - $h) );
}
sub circle_segment_r($$) {
    my $s = shift;
    my $h = shift;
    my $r = ($s*$s/4 + $h*$h) / (2*$h);
}
sub circle_segment_angle($$) {
    my $s = shift;
    my $h = shift;
    my $r = circle_segment_r($s, $h);
    my $angle = asin($s/(2*$r));
}

sub stat_linreg($$) {
    my $xr = shift;
    my $yr = shift;

    my @x = @$xr;
    my @y = @$yr;
    if (@x != @y || @x == 0) {
	printf "Err (stat_linreg): arrays of lengths %d %d\n", @x+0, @y+0;
	return [0, 0];
    }
    my $a0 = 0;
    my $a1 = 0;

    my $n  = @x+0;
    my $x  = 0;
    my $y  = 0;
    my $xx = 0;
    my $xy = 0;
    for (my $ix = 0; $ix < @x; $ix++) {
	$x += $x[$ix];
	$y += $y[$ix];
	$xx += $x[$ix] * $x[$ix];
	$xy += $x[$ix] * $y[$ix];
    }
    #printf "%.1f %.1f %.1f %.1f\n", $x, $y, $xx, $xy;

    #
    my $b = $n * $xx - $x * $x;
    if ($b == 0) {
	printf "Err (stat_linreg): divide by zero\n";
	return [0, 0];
    }
    $a0 = ($y  * $xx - $xy * $x) / $b;
    $a1 = ($xy * $n  - $y  * $x) / $b;

    ($a0, $a1);
}
sub stat_linreg_test() {
    my @x = (4.0, 7.0, 8.0, 9.0, 10.0);
    my @y = (3.0, 4.5, 5.0, 6.1,  6.4);
    my @a = stat_linreg(\@x, \@y);
    printf("%.3f %.3f\n", @a);
    # 0.555 0.585
}
#stat_linreg_test();

# vetor things, point or vector = [ $x, $y ]
sub vec_length($) { # returns length of a vector
    my $v = shift;
    sqrt($$v[0]*$$v[0] + $$v[1]*$$v[1]);
}

sub vec_angle($) { # gives a vectors angle to the x-axis
    my $v = shift;
    - atan2($$v[1], $$v[0]);
}

sub vec_polar($) {
    my $p = shift;
    my $r = vec_length($p);
    my $a = vec_angle($p);
    [ $r, $a ];
}

sub polar_vec($) {
    my $p = shift;
    my $r = $$p[0];
    my $a = $$p[1];

    [ - $r * cos($a), $r * sin($a) ];
}

sub vec_normal( $ ) { # returns a rotated +90°
    my $a = shift;
    [ -$$a[1], $$a[0] ];
}

sub vec_nnormal( $ ) { # returns a rotated -90°
    my $a = shift;
    [ $$a[1], -$$a[0] ];
}

sub vec_reverse($) { # returns a rotated 180°
    my $a = shift;
    [ -$$a[0], -$$a[1] ];
}

sub vec_xmirror($) { # same y, but -x
    my $a = shift;
    [ -$$a[0], $$a[1] ];
}

sub vec_ymirror($) { # same x, but -y
    my $a = shift;
    [ $$a[0], -$$a[1] ];
}

sub vec_mul($$) { # returns $k * $b
    my $k = shift;
    my $b = shift;

    my @res = (0) x @$b;
    for (my $ix = 0; $ix < @$b; $ix++) {
	$res[$ix] = $k * $$b[$ix];
    }
    [ @res ];
}
sub vec_sadd( $ $ ) { # result[:] = a + b[:]
    my $a = shift;
    my $b = shift;
    my @res = ();

    @res = (0) x @$b;
    for (my $ix = 0; $ix < @$b; $ix++) {
	$res[$ix] = $a + $$b[$ix];
    }
    [ @res ];
}

sub vec_e($) { # returns a's unit vector
    my $a = shift;
    my $l = vec_length($a);
    my $e;
    if ($l > 0) {
	$e = vec_mul( 1/$l, $a);
	#$$e[0] /= $l;
	#$$e[1] /= $l;
    } else { # when $a == [ 0, 0 ], no complex numbers
	$e = [ 1, 0 ]; # TODO, what's the unit vector of (0, 0) ?
    }
    $e;
}

sub vec_sub( $ $ ) { # result = a - b
    my $a = shift;
    my $b = shift;
    my @res = ();

    if (@$a == @$b) {
	@res = (0) x @$a;
	for (my $ix = 0; $ix < @$a; $ix++) {
	    $res[$ix] = $$a[$ix] - $$b[$ix];
	}
    } else {
	warn("unequal input array lengths");
    }
    [ @res ];
}

sub vec_add(@) { # result = a + b + ...
    my @res = ();
    my $dim = 0;

    for my $a (@_) {
	if ($dim < @$a) { $dim = @$a; }

	for (my $ix = 0; $ix < $dim; $ix++) {
	    if (defined($$a[$ix])) {
		if (defined($res[$ix])) {
		    $res[$ix] += $$a[$ix];
		} else {
		    $res[$ix] = $$a[$ix];
		}
	    }
	}
    }

    [ @res ];
}

sub vec_distance( $ $ ) { # = distance between point a and b
    my $a = shift;
    my $b = shift;

    vec_length(vec_sub($b, $a));
}

sub vec_inner_product($ $) { # result (a scalar) = a · b
    my $a = shift;
    my $b = shift;

    $$a[0] * $$b[0] + $$a[1] * $$b[1];
}

sub vec_print($) { # print out a vectors x and y value (mostly for debugging)
    my $v = shift;
    print "\[ $$v[0], $$v[1] \]\n";
}

sub vec_diff_angle( $ $ ) { # = angle between a and b
    my $a = shift;
    my $b = shift;

    my $s = vec_angle($a);
    my $t = vec_angle($b);

    my $d = $t - $s;
    rad_normalize1($d);
}

sub vec_normal_point( $ $ $ ) { # returns point on line trough a and b where the lines normal goea through c
    my $a = shift;
    my $b = shift;
    my $c = shift;

    # translate everything to origo
    $b = vec_sub($b, $a);
    $c = vec_sub($c, $a);

    my $l = vec_length($b);
    my $r;

    if ($l > 0) {
	my $d = vec_diff_angle($b, $c);
	my $s = vec_length($c);
	my $k = cos($d) * $s / $l;
	$r = vec_mul($k, $b);
	$r = vec_add($a, $r);
    } else { # we only have two points
	$r = $a;
    }

    $r;
}

sub vec_test(@){
    if (@_ < 4) {
       die("need 4 arguments");
    }

    my $a = [ shift, shift ];
    my $b = [ shift, shift ];
    my $origo = [ 0, 0 ];
    my $vs = vec_sub($a, $b);
    my $va = vec_add($a, $b);
    print "vec_length: ", vec_length($a), " ", vec_length($b), "\n";
    print "vec_sub:    "; vec_print($vs);
    print "vec_add:    "; vec_print($va);
    print "inner prod: ", vec_inner_product($a, $b), "\n";
    my $c = vec_angle($a);
    print "vec_angle:  ", $c, " ", rad_deg($c), "\n";
    $c = vec_diff_angle($a, $b);
    print "diff angle: ", $c, " ", rad_deg($c), "\n";
    my $d = vec_normal_point($origo, $a, $b);
    print "normal p:   "; vec_print($d);
}

my $rot_cos = 1;
my $rot_sin = 0;
sub rot_init($) {
    my $angle = shift;
    my $rad = $pi*$angle/180;
    $rot_cos = cos($rad);
    $rot_sin = sin($rad);
}
sub rot($$) {
    my $x = shift;
    my $y = shift;

    my $X =   $x * $rot_cos + $y * $rot_sin;
    my $Y = - $x * $rot_sin + $y * $rot_cos;
    ( $X, $Y );
}
sub vrot($) {
    my $v = shift;
    my ($X, $Y) = rot($$v[0], $$v[1]);
    [ $X, $Y ];
}

#vec_test(@ARGV);

########################################

# bb, bounding boxes [ xmin, xmax, ymin, ymax ], xmin <= xmax, ymin <= ymax
sub bb_clear() {
  $bbx1 = undef;
  $bbx2 = undef;
  $bby1 = undef;
  $bby2 = undef;
  @bounding_box = ();
}
sub bb_extend($$) {
    # make bounding box bb cover point p
    my $p  = shift;
    my $bb = shift;

    my $x = $$p[0];
    my $y = $$p[1];

    if ($x < $$bb[0]) { $$bb[0] = $x; }
    if ($x > $$bb[1]) { $$bb[1] = $x; }
    if ($y < $$bb[2]) { $$bb[2] = $y; }
    if ($y > $$bb[3]) { $$bb[3] = $y; }
    $bb;
}
sub bb_inside($$) {
    # point p is inside bounding box bb
    # i.e. not on the border or outside
    my $p = shift;
    my $bb = shift;

    my $x = $$p[0];
    my $y = $$p[1];
    my @bb = @$bb;

    if ($bb[0] < $x && $x < $bb[1] && $bb[2] < $y && $y < $bb[3]) {
	return 1;
    }
    return 0;
}
sub bb_sort(@) {
    # sort by position, x-vise first, then y-vise, and lastly by pin number
    my @arr;
    @arr = sort { $$a[0] <=> $$b[0] || $$a[1] <=> $$b[1] || $$a[2] <=> $$b[2] || $$a[3] <=> $$b[3] || $$a[4] <=> $$b[4] } @_;
}
#sub bb_overlap($$) {
#    # does two bounding boxes overlap or touch each other
#    my $bb1 = shift;
#    my $bb2 = shift;
#
#    my $ret = 0;
#
#    my $bb1c = [ ($$bb1[1] + $$bb1[0])/2, ($$bb1[3] + $$bb1[2])/2 ]; # bb center
#    my $bb1z = [ ($$bb1[1] - $$bb1[0])/2, ($$bb1[3] - $$bb1[2])/2 ]; # bb center to corner length
#    my $bb2c = [ ($$bb2[1] + $$bb2[0])/2, ($$bb2[3] + $$bb2[2])/2 ];
#    my $bb2z = [ ($$bb2[1] - $$bb2[0])/2, ($$bb2[3] - $$bb2[2])/2 ];
#
#    my $testc = vec_sub($bb1c, $bb2c);  # think: translate bb1 to bb2's center
#
#    # since bb2@origin is symmetric around x- and y-axis
#    if ($$testc[0] < 0) { $$testc[0] = - $$testc[0]; }
#    if ($$testc[1] < 0) { $$testc[1] = - $$testc[1]; }
#
#    my $testp = vec_sub($testc, $bb1z); # to get translated bb2's top left corner point
#    if ($$testp[0] < $$bb2z[0] && $$testp[1] < $$bb2z[1]) { $ret = 1; }
#
#    $ret;
#}
sub bb_print(@) {
    for my $rr (@_) {
	my @r = @$rr;
	printf("  %7.3f %7.3f %7.3f %7.3f,   %s\n", $r[0], $r[1], $r[2], $r[3], join(", ", @r[4..$#r]));
    }
}
sub bb_enlarge($@) {
    my $sz = shift;
    my @arr = @_;
    my @new = ();

    for my $rr (@arr) {
	my @r = @$rr;
	my $rr = $r[5];
#	if ($r[5]) {}
	$r[5] += $sz;
	push @new, [ $r[0] - $sz, $r[1] + $sz, $r[2] - $sz, $r[3] + $sz, @r[4..$#r] ];
    }
    @new;
}
sub bb_show(@) {
    my $save = $silk_w;
    silk_width(0.001);
    for my $r (@_) {
	silk_rect([$$r[0], $$r[2]], [ $$r[1], $$r[3]], $$r[5]);
    }
    silk_width($save);
}
sub bb_showit(@) {
    my $w = $silk_w/2 * 1.01;
    my @bbw = bb_enlarge($silk_w/2,@bounding_box);
    for my $r (@_) {
	silk_rect([$$r[0]-$w, $$r[2]-$w], [ $$r[1]+$w, $$r[3]+$w], 0, \@bbw);
    }
}
sub bb_tlcorner(@) {
    my $w = $silk_w/2 * 1.01;
    my @bbw = bb_enlarge($silk_w/2,@bounding_box);
    #bb_print($r);
    for my $r (@_) {
	silk_start($$r[1]   , $$r[2]-$w);
	silk_line ($$r[0]-$w, $$r[2]-$w, \@bbw);
	silk_line ($$r[0]-$w, $$r[3]   , \@bbw);
    }
}
sub bb_blcorner(@) {
    my $w = $silk_w/2 * 1.01;
    my @bbw = bb_enlarge($silk_w/2,@bounding_box);
    for my $r (@_) {
	silk_start($$r[0]-$w, $$r[2]);
	silk_line ($$r[0]-$w, $$r[3]+$w, \@bbw);
	silk_line ($$r[1]   , $$r[3]+$w, \@bbw);
    }
}
sub bb_brcorner(@) {
    my $w = $silk_w/2 * 1.01;
    my @bbw = bb_enlarge($silk_w/2,@bounding_box);
    #bb_print($r);
    for my $r (@_) {
	silk_start($$r[0]   , $$r[3]+$w);
	silk_line ($$r[1]+$w, $$r[3]+$w, \@bbw);
	silk_line ($$r[1]+$w, $$r[2]   , \@bbw);
    }
}
sub bb_trcorner(@) {
    my $w = $silk_w/2 * 1.01;
    my @bbw = bb_enlarge($silk_w/2,@bounding_box);
    #bb_print($r);
    for my $r (@_) {
	silk_start($$r[1]+$w, $$r[3]   );
	silk_line ($$r[1]+$w, $$r[2]-$w, \@bbw);
	silk_line ($$r[0]   , $$r[2]-$w, \@bbw);
    }
}
sub bb_left_side(@) {
    my $w = $silk_w/2 * 1.01;
    my @bbw = bb_enlarge($silk_w/2,@bounding_box);
    for my $r (@_) {
	silk_start($$r[0]-$w, $$r[2]);
	silk_line ($$r[0]-$w, $$r[3]);
    }
}
sub bb_right_side(@) {
    my $w = $silk_w/2 * 1.01;
    my @bbw = bb_enlarge($silk_w/2,@bounding_box);
    for my $r (@_) {
	silk_start($$r[1]+$w, $$r[2]);
	silk_line ($$r[1]+$w, $$r[3]);
    }
}
sub bb_top_side(@) {
    my $w = $silk_w/2 * 1.01;
    my @bbw = bb_enlarge($silk_w/2,@bounding_box);
    for my $r (@_) {
	silk_start($$r[0], $$r[2]-$w);
	silk_line ($$r[1], $$r[2]-$w);
    }
}
sub bb_bottom_side(@) {
    my $w = $silk_w/2 * 1.01;
    my @bbw = bb_enlarge($silk_w/2,@bounding_box);
    for my $r (@_) {
	silk_start($$r[0], $$r[3]+$w);
	silk_line ($$r[1], $$r[3]+$w);
    }
}
sub bb_left_hat(@) {
    my $w = $silk_w/2 * 1.01;
    my @bbw = bb_enlarge($silk_w/2,@bounding_box);
    for my $r (@_) {
	my $half_x = (4*$$r[0] + $$r[1])/5;
	silk_start($half_x  , $$r[2]-$w);
	silk_line ($$r[0]-$w, $$r[2]-$w, \@bbw);
	silk_line ($$r[0]-$w, $$r[3]+$w, \@bbw);
	silk_line ($half_x  , $$r[3]+$w);
    }
}
sub bb_index_position(@) {
    my @bbw = @_;
    @bbw = grep { $$_[4] > 0 } @bbw;
    @bbw = sort { $$a[4] <=> $$b[4] } @bbw;
    # bb_one: pad with the lowest pin number
    # bbc: bb_one's center
    my $bb_one = $bbw[0];
    my $bbc = [ ($$bb_one[1] + $$bb_one[0])/2, ($$bb_one[3] + $$bb_one[2])/2 ];
    my $ipos = "";
    my $ipnt = [ 0, 0 ];
    if        ($$bbc[0] < 0) {
	if    ($$bbc[1] < 0) { $ipos = 'tl'; $ipnt = [ -1, -1 ]; } # top left
	elsif ($$bbc[1] > 0) { $ipos = 'bl'; $ipnt = [ -1,  1 ]; } # bottom left
	else                 { $ipos = 'cl'; $ipnt = [ -1,  0 ]; } # center left
    } elsif   ($$bbc[0] > 0) {
	if    ($$bbc[1] < 0) { $ipos = 'tr'; $ipnt = [  1, -1 ]; } # top right
	elsif ($$bbc[1] > 0) { $ipos = 'br'; $ipnt = [  1,  1 ]; } # bottom right
	else                 { $ipos = 'cr'; $ipnt = [  1,  0 ]; } # center rigth
    } else { # x-center on y-axis
	if    ($$bbc[1] < 0) { $ipos = 'tc'; $ipnt = [  0, -1 ]; } # top center
	elsif ($$bbc[1] > 0) { $ipos = 'bc'; $ipnt = [  0,  1 ]; } # bottom center
	else                 { $ipos = 'cc'; $ipnt = [  0,  0 ]; } # center center
    }
    ( $ipos, $ipnt, $bb_one, $bbc );
}

sub bb_OfAnArc($$$$) {
    my $pos = shift; # [x,y] of arc center
    my $r = shift;   # 0 < $r
    my $sta = shift; # 0 <= $sta < 360
    my $sweep = shift; # 0 <= $sweep <= 360

    my $end = $sta + $sweep;

    # bb of the first point
    my $box = [ -Cos($sta), -Cos($sta), Sin($sta), Sin($sta) ];
    bb_extend( [ -Cos($end), Sin($end) ], $box);
    for (my $ix = roundup($sta, 90); $ix < $end; $ix += 90) {
	bb_extend( [ -Cos($ix), Sin($ix) ], $box);
    }
    $box = [
	$r * $$box[0] + $$pos[0],
	$r * $$box[1] + $$pos[0],
	$r * $$box[2] + $$pos[1],
	$r * $$box[3] + $$pos[1]
    ];

    $box;
}

# line from one circle to another, tangent to booth
sub c2c_inclination($$$$;$) {
    my $center1 = shift;
    my $center2 = shift;
    my $radi1 = shift;
    my $radi2 = shift;
    my $isOnSameSide = shift // 0;

    my $d = vec_distance($center1, $center2);

    if ($isOnSameSide) {
	my @radi = sortNumbers($radi1, $radi2);
	if ($d + $radi[0] < $radi[1]) {
	    # onne circle is withing the other, no line possible
	    return ();
	}
	return ($radi1 - $radi2, $d);
    } else { # on other side
	if ($d < $radi1 + $radi2) {
	    # not possible to connect with a line when the circles intersect
	    return ();
	}
	return ($radi1 + $radi2, $d);
    }
}
sub c2c_angle($$$$;$) {
    my $center1 = shift;
    my $center2 = shift;
    my $radi1 = shift;
    my $radi2 = shift;
    my $isOnSameSide = shift // 0;

    my @arr = c2c_inclination($center1, $center2, $radi1, $radi2, $isOnSameSide);
    if (@arr && $arr[1] > 0) {
	return asin($arr[0] / $arr[1]);
    } else {
	return undef;
    }
}
sub c2c_Angle($$$$;$) {
    my $center1 = shift;
    my $center2 = shift;
    my $radi1 = shift;
    my $radi2 = shift;
    my $isOnSameSide = shift // 0;

    my $rad = c2c_angle($center1, $center2, $radi1, $radi2, $isOnSameSide);
    if (!defined($rad)) {
	return undef;
    } else {
	return rad_deg($rad);
    }
}

################

sub silk_width(;$) {
    my $w = shift;
    if (!defined($w)) { $w = $silk_default; }
    $silk_w = $w;
    $silk_width = mk_mm($w);
}
silk_width();

sub silk_start($$) {
  $silk_x = shift;
  $silk_y = shift;
  $silk_xmm = mk_mm($silk_x);
  $silk_ymm = mk_mm($silk_y);
  #print "$silk_x $silk_y start\n";
}

sub silk_vstart($) {
    my $r = shift;
    silk_start($$r[0], $$r[1]);
}

sub silk_line_vertical($$$) {
  my $x = shift;
  my $y = shift;
  my $bb = shift;

  my @bb;
  my $nn = 0;

  my $min = $y;
  if ($min > $silk_y) { $min = $silk_y; }
  my $max = $y;
  if ($max < $silk_y) { $max = $silk_y; }

  @bb = grep { $x >= $$_[0] } @$bb;
  @bb = grep { $x <= $$_[1] } @bb;
  @bb = grep { $max >= $$_[2] } @bb;
  @bb = grep { $min <= $$_[3] } @bb;
  @bb = sort { $$a[2] <=> $$b[2] || $$a[3] <=> $$b[3] } @bb;

  my $sta = $min;
  my $end = $max;
  for my $r (@bb) {
      if ($sta <= $$r[2]) {
	  silk_start($x, $sta);
	  $sta = $$r[3];
	  if ($end <= $$r[2]) {
	      $nn += silk_line( $x, $end);
	      last;
	  } else {
	      $nn += silk_line( $x, $$r[2]);
	  }
      } else {
	  $sta = $$r[3];
	  if ($sta > $end) { last; }
      }
  }
  if ($sta < $end) {
      silk_start($x, $sta);
      $nn += silk_line( $x, $end);
  }
  return $nn;
}

sub silk_line_horizontal($$$) {
  my $x = shift;
  my $y = shift;
  my $bb = shift;

  my $nn = 0;
  my @bb;

  my $min = $x;
  if ($min > $silk_x) { $min = $silk_x; }
  my $max = $x;
  if ($max < $silk_x) { $max = $silk_x; }

  @bb = grep { $y >= $$_[2] } @$bb;
  @bb = grep { $y <= $$_[3] } @bb;
  @bb = grep { $max >= $$_[0] } @bb;
  @bb = grep { $min <= $$_[1] } @bb;
  @bb = sort { $$a[0] <=> $$b[0] || $$a[1] <=> $$b[1] } @bb;

  my $sta = $min;
  my $end = $max;
  for my $r (@bb) {
      if ($sta <= $$r[0]) {
	  silk_start($sta, $y);
	  $sta = $$r[1];
	  if ($end <= $$r[0]) {
	      $nn += silk_line( $end, $y);
	      last;
	  } else {
	      $nn += silk_line($$r[0], $y);
	  }
      } else {
	  $sta = $$r[1];
	  if ($sta > $end) { last; }
      }
  }
  if ($sta < $end) {
      silk_start($sta, $y);
      $nn += silk_line( $end, $y);
  }
  return $nn;
}

sub silk_line_bb($$$) {
  my $x = shift;
  my $y = shift;
  my $bb = shift;

  if ($x == $silk_x) {		# vertical line
      return silk_line_vertical($x, $y, $bb);
  } elsif ($y == $silk_y) {	# horizontal line
      return silk_line_horizontal($x, $y, $bb);
  }

  #print "\nsilk_line_bb: $silk_x $silk_y $x $y\n";
  my $nn = 0;
  my @bb = @$bb;

  my $xmin = $x;
  if ($xmin > $silk_x) { $xmin = $silk_x; }
  my $xmax = $x;
  if ($xmax < $silk_x) { $xmax = $silk_x; }

  my $ymin = $y;
  if ($ymin > $silk_y) { $ymin = $silk_y; }
  my $ymax = $y;
  if ($ymax < $silk_y) { $ymax = $silk_y; }

  @bb = grep { $xmax >= $$_[0] } @bb;
  @bb = grep { $xmin <= $$_[1] } @bb;
  @bb = grep { $ymax >= $$_[2] } @bb;
  @bb = grep { $ymin <= $$_[3] } @bb;

  my $A = [ $silk_x, $silk_y ]; # starting point
  my $B = [ $x, $y ];           # end point
  my $AB = vec_sub($B, $A);
  my $len = vec_length($AB);
  #print "  len: $len\n";
  if ($len == 0) { # a dot
      return silk_line($x, $y);
  }
  my $e = vec_mul(1/$len, $AB);
  #print "  e: $$e[0], $$e[1]\n";

  #my ($ls, $bs, $rs, $ts) = qw/ left bottom right top /; # line A-B, intersect with bb on this side

  my @block = ();
  # find if silk line $A to $B collides with any bounding box area (i.e. where copper is)
  for my $r (@bb) {
      my ($dx, $dy, $s, $X, $Y);
      my @list = ();

      my $Ai = bb_inside($A,$r);
      my $Bi = bb_inside($B,$r);
      #print "  bb: $Ai $Bi ";
      #bb_print($r);
      if ($Ai == 1) {
	  push @list, [ 0, $A ];
      }
      if ($Bi == 1) {
	  push @list, [ $len, $B ];
      }

      # left side
      $X = $$r[0];
      $dx = $X - $$A[0];
      $s = $dx / $$e[0];
      $dy = $s * $$e[1];
      $Y = $$A[1] + $dy;
      if (0 <= $s && $s <= $len && $$r[2] <= $Y && $Y <= $$r[3]) {
	  push @list, [ $s, [ $X, $Y ] ];
      }

      # right side
      $X = $$r[1];
      $dx = $X - $$A[0];
      $s = $dx / $$e[0];
      $dy = $s * $$e[1];
      $Y = $$A[1] + $dy;
      if (0 <= $s && $s <= $len && $$r[2] <= $Y && $Y <= $$r[3]) {
	  push @list, [ $s, [ $X, $Y ] ];
      }

      # top side
      $Y = $$r[2];
      $dy = $Y - $$A[1];
      $s = $dy / $$e[1];
      $dx = $s * $$e[0];
      $X = $$A[0] + $dx;
      if (0 <= $s && $s <= $len && $$r[0] <= $X && $X <= $$r[1]) {
	  push @list, [ $s, [ $X, $Y ] ];
      }

      # bottom side
      $Y = $$r[3];
      $dy = $Y - $$A[1];
      $s = $dy / $$e[1];
      $dx = $s * $$e[0];
      $X = $$A[0] + $dx;
      if (0 <= $s && $s <= $len && $$r[0] <= $X && $X <= $$r[1]) {
	  push @list, [ $s, [ $X, $Y ] ];
      }
      if (@list == 0) {
	  # ok
      } elsif (@list == 2) {
	  # ok
	  if ($list[0][0] != $list[1][0]) {
	      @list = sort { $$a[0] <=> $$b[0] } @list;
	      push @block, \@list;
	  } else {
	      # a block of length 0, ignore
	  }
      } else {
	  print "strange list\n";
      }
  }
  @block = sort { $$a[0][0] <=> $$b[0][0] || $$a[1][0] <=> $$b[1][0] } @block;

  my $sta = [ 0, $A ];
  my $end = [ $len, $B ];
  for my $r (@block) {
      my $block_sta = $$r[0];
      my $block_end = $$r[1];
      if ($$sta[0] <= $$block_sta[0]) {
	  silk_vstart($$sta[1]);
	  $sta = $block_end;
	  if ($$end[0] <= $$block_sta[0]) {
	      $nn += silk_vline($$end[1]);
	      last;
	  } else {
	      $nn += silk_vline($$block_sta[1]);
	  }
      } else {
	  $sta = $block_end;
	  if ($$sta[0] > $$end[0]) { last; }
      }
  }
  if ($$sta[0] < $$end[0]) {
      silk_vstart($$sta[1]);
      $nn += silk_vline($$end[1]);
  }

  return $nn;
}

sub silk_line($$;$) {
  my $x = shift;
  my $y = shift;
  my $bb = shift;

  my $xmm = mk_mm($x);
  my $ymm = mk_mm($y);

  my $nn = 0;
#  my $d = triangle_r($x-$silk_x, $y-$silk_y);
#  if ($d >= $silk_w * 0.7 && $d >= 0.25) {
      if (defined($bb)) {
	      $nn += silk_line_bb($x, $y, $bb);
      } else {
	  pr "ElementLine [ $silk_xmm $silk_ymm $xmm $ymm  $silk_width ]\n";
	  $nn += 1;
      }
#  }

  $silk_x = $x;
  $silk_y = $y;
  $silk_xmm = mk_mm($silk_x);
  $silk_ymm = mk_mm($silk_y);
  return $nn;
}
sub silk_vline($;$) {
    my $r = shift;
    my $bb = shift;

    return silk_line($$r[0], $$r[1], $bb);
}

sub silk_rline($$;$) {
  my $x = $silk_x + shift;
  my $y = $silk_y + shift;
  my $bb = shift;

  return silk_line($x, $y, $bb);
}
sub silk_vrline($;$) {
    my $r = shift;
    my $bb = shift;
    return silk_rline($$r[0], $$r[1], $bb);
}

sub silk_cross($$$;$) {
    my $x = shift;
    my $y = shift;
    my $l = shift;
    my $w = shift;

    my $tmp = $silk_width;
    if ($w) { silk_width($w); }
    silk_start( $x + $l/2, $y       ); silk_rline( -$l,   0);
    silk_start( $x       , $y + $l/2); silk_rline(   0, -$l);
    $silk_width = $tmp;
}

sub silk_fillleft($$$$$) {
    my $left = shift; # x for left limit/line
    my $top = shift; # y for top limit/line
    my $bot = shift; # y for bottom limit/line
    my $cr  = shift; # corner radius

    my $brd = shift; # [ brd_h, brd_w ]
    my $brd_h = $$brd[0]; # dist. from $left to line at right limit
    my $brd_w = $$brd[1]; # silkwidth of right limit, <= 0 : no line drawn
    if (!defined($brd_w)) { $brd_w = $silk_default; }

    my $fill = shift; # [ fill_type, fill_h, fill_a ]
    if (!defined($fill) || !defined($$fill[0])) { $fill = [ 0 ]; }
    if (!defined($$fill[1])) { $$fill[1] = 45; };
    if (!defined($$fill[2])) { $$fill[2] = 0.12; };
    my $fill_h = $$fill[0];
    my $fill_a = $$fill[1];
    my $fill_w = $$fill[2];

    my $t = $top;
    my $b = $bot;
    if ($brd_h < $cr) {
	my $seg = circle_segment_s($cr, $brd_h)/2;
	my $d = $cr - $seg;
	$t += $d;
	$b -= $d;
    }

    if ($brd_w > 0) {
	silk_width($brd_w);
	silk_start($left+$brd_h, $t);
	silk_line($left+$brd_h, $b);
    }

    if ($fill_h > 0) {
	my $rad = deg_rad($fill_a);
	my $vl = [ cos($rad), -sin($rad) ]; # since +y is down
	my $vn = vec_normal($vl);
	silk_width($fill_w);

	my $tc  = [ $left+$cr, $top + $cr ];
	my $bc  = [ $left+$cr, $bot + $cr ];
	my $mid = [ ($left + $brd_h)/2, ($top+$bot)/2 ];
    }

    silk_width();
}
sub test_fill() {
    my $xw = $ARGV[0];
    my $yw = $ARGV[1];
    my $cr = $ARGV[2];
    my $h  = $ARGV[3];

    my $file = "test_fill.fp";
    my $doc = "";
    element_start($file, $doc);
    pin( -5, 0, 1, 2);
    pin(  5, 0, 1, 2);

    silk_crect($origin, [$xw, $yw], $cr);
    my $brd = [ $h ];
    silk_fillleft(-$xw/2, -$yw/2, $yw/2, $cr, $brd);
    element_stop();
    exit(0);
}
#test_fill();
sub silk_rectr($;$) {
    my $rr = shift;
    my $bb = shift;
    my ($min, $max, $r, $flag, $markings) = @$rr;
    silk_rect($min, $max, $r, $bb, $flag, $markings);
}
sub silk_rect($$;$$$$$) {
    my $min = shift; # [x,y]
    my $max = shift;

    my $r = shift; # > 0: corner raduis, < 0: cut corner
    my $bb = shift;
    my $flag = shift; # to not draw the bottom line/border
    my $markings = shift; # +/-45°, 0 and 90° hashed, filled, single line

    if (!defined($r)) { $r = 0; }
    my $nn = 0; # return value = # of lines drawn
    # dil/lqfp order:
    #  corners: top left, bot.left, bot.right, top right
    #  sides: left, bot, right, top
    my @cut = (0,0,0,0); # 0: arc (a round corner), 1: straight line (a cut corner)
    my @cr = (0,0,0,0); # corner radi
    my @cp; # same order as @r
    my @cc; # corner radi centers, same order as @r
    my $circle = 0;

    if (ref($r) eq "ARRAY") {
	@cr = @$r;
    } else {
	$circle = $r;
	@cr = ($r, $r, $r, $r);
    }
    for (my $ix = 0; $ix < @cr; $ix++) {
	if ($cr[$ix] < 0) {
	    $cr[$ix] = - $cr[$ix];
	    $cut[$ix] = 1;
	}
    }
    # just accept any two corners
    if ($$min[0] > $$max[0]) { my $tmp = $$min[0]; $$min[0] = $$max[0]; $$max[0] = $tmp; }
    if ($$min[1] > $$max[1]) { my $tmp = $$min[1]; $$min[1] = $$max[1]; $$max[1] = $tmp; }

    $cp[0] = [ $$min[0], $$min[1] ]; # top  left
    $cp[1] = [ $$min[0], $$max[1] ]; # bot. left
    $cp[2] = [ $$max[0], $$max[1] ]; # bot. right
    $cp[3] = [ $$max[0], $$min[1] ]; # top  right

    # check radiues
    my $xl = $$max[0] - $$min[0]; # x length >= 0
    my $yl = $$max[1] - $$min[1]; # y length >= 0
    if ($yl < $cr[0] + $cr[1]) { # left
	$cr[0] = $yl * $cr[0] / ($cr[0] + $cr[1]);
	$cr[1] = $yl * $cr[1] / ($cr[0] + $cr[1]);
    }
    if ($xl < $cr[1] + $cr[2]) { # bottom
	$cr[1] = $xl * $cr[1] / ($cr[1] + $cr[2]);
	$cr[2] = $xl * $cr[2] / ($cr[1] + $cr[2]);
    }
    if ($yl < $cr[2] + $cr[3]) { # right
	$cr[2] = $yl * $cr[2] / ($cr[2] + $cr[3]);
	$cr[3] = $yl * $cr[3] / ($cr[2] + $cr[3]);
    }
    if ($xl < $cr[3] + $cr[0]) { # top
	$cr[3] = $xl * $cr[3] / ($cr[3] + $cr[0]);
	$cr[0] = $xl * $cr[0] / ($cr[3] + $cr[0]);
    }

    my $x1n = mk_mm($$min[0]);
    my $x2n = mk_mm($$max[0]);
    my $y1n = mk_mm($$min[1]);
    my $y2n = mk_mm($$max[1]);
    # corner: radi center
    $cc[0] = [ $cp[0][0] + $cr[0], $cp[0][1] + $cr[0] ];
    $cc[1] = [ $cp[1][0] + $cr[1], $cp[1][1] - $cr[1] ];
    $cc[2] = [ $cp[2][0] - $cr[2], $cp[2][1] - $cr[2] ];
    $cc[3] = [ $cp[3][0] - $cr[3], $cp[3][1] + $cr[3] ];

    my $line_left  = $cc[0][1] < $cc[1][1];
    my $line_bot   = $cc[1][0] < $cc[2][0];
    my $line_right = $cc[3][1] < $cc[2][1];
    my $line_top   = $cc[0][0] < $cc[3][0];

    if ($line_left) {
	silk_start($$min[0], $cc[0][1]);
	$nn += silk_line( $$min[0], $cc[1][1], $bb);
    }
    if (!$flag) {
	if ($line_bot) {
	    silk_start($cc[1][0], $$max[1]);
	    $nn += silk_line( $cc[2][0], $$max[1], $bb);
	}
    }
    if ($line_right) {
	silk_start($$max[0], $cc[2][1]);
	$nn += silk_line( $$max[0], $cc[3][1], $bb);
    }
    if ($line_top  ) {
	silk_start($cc[3][0], $$min[1]);
	$nn += silk_line( $cc[0][0], $$min[1], $bb);
    }

    if ($circle) {
	silk_arc($cc[0], $circle, 0, 360, $bb);
    } else {
	for (my $ix = 0; $ix < @cr; $ix++) {
	    if ($cr[$ix]) {
		if ($cut[$ix]) {
		    my $sk = 2*$ix - 2;
		    my $ek = 2*$ix;
		    if ($sk < 0) { $sk += @sweep; }
		    silk_start($cc[$ix][0] + $sweep[$sk][0] * $cr[$ix], $cc[$ix][1] + $sweep[$sk][1] * $cr[$ix]);
		    silk_line ($cc[$ix][0] + $sweep[$ek][0] * $cr[$ix], $cc[$ix][1] + $sweep[$ek][1] * $cr[$ix], $bb);
		    $nn++;
		} else {
		    my $sta = sprintf("%3d", -90 + 90 * $ix); # start angle, sweep is 90
		    silk_arc($cc[$ix], $cr[$ix], $sta, 90, $bb);
		    $nn++;
		}
	    }
	}
    }
    $nn;
}

sub silk_crectr($$;$) {
    my $offset = shift;
    my $rr = shift;
    my $bb = shift;
    my ($sz, $r, $flag) = @$rr;
    silk_crect($offset,$sz,$r,$bb,$flag);
}
sub silk_crect($$;$$$) {
    my $center = shift;
    my $sz     = shift;

    my $r      = shift;
    my $bb     = shift;
    my $flag   = shift;

    my $min = vec_sub($center, vec_mul(0.5, $sz));
    my $max = vec_add($min, $sz);
    silk_rect( $min, $max, $r, $bb, $flag);
}
sub silk_blrect($$;$$$) {
    my $bl     = shift;
    my $sz     = shift;

    my $r      = shift;
    my $bb     = shift;
    my $flag   = shift;

    my $min = $bl;
    my $max = vec_add($min, $sz);
    silk_rect( $min, $max, $r, $bb, $flag);
}

sub silk_sq($;$$$) {
    my $w      = shift;

    my $r      = shift;
    my $bb     = shift;
    my $flag   = shift;

    $w /= 2;
    my $min = [ -$w, -$w ];
    my $max = [  $w,  $w ];
    silk_rect($min, $max, $r);
}

sub rangePrint(@) {
    my @range = @_;
    print "[ ";
    for my $r (@range) {
	my ($a, $b) = @$r;
	print "[$a,$b], ";
    }
    print "]\n";
}
sub rangeSort(@) {
    my @range = @_;

    sort { $$a[0] <=> $$b[0]  || $$b[1] <=> $$a[1] } @range;
}
sub rangeMerge(@) {
    my @range = @_; # must be sorted

    if (@range > 1) {
	my @a = ();
	my $f = shift @range;
	while (@range) {
	    my $tst = shift @range;
	    if ($$tst[0] <= $$f[1]) {
		if ( $$f[1] < $$tst[1] ) {
		    $f = [ $$f[0], $$tst[1] ];
		}
	    } else {
		push @a, $f;
		$f = $tst;
	    }
	}
	push @a, $f;
	@range = @a;
    }
    @range;
}
sub rangeWrap($@) {
    my $max = shift;
    my @range = @_;

    my @a = ();
    for my $rr (@range) {
	my ($sta, $end) = @$rr;
	while ($sta < 0) {
	    $sta += $max;
	    $end += $max;
	}
	while ($sta >= $max) {
	    $sta -= $max;
	    $end -= $max;
	}
	if ($max < $end) {
	    push @a, [$sta, $max], [0, $end-$max];
	} else {
	    push @a, [$sta, $end];
	}
    }
    @range = rangeMerge(rangeSort(@a));
}
sub rangeAdd(\@@) {
    my $inta = shift;
    my @data = @_;

    my @range = @$inta;
    push @range, @data;
    @range = rangeSort(@range);
    @range = rangeMerge(@range);
}
sub rangeExcl(\@@) {
    my $inta = shift;
    my @excl = @_;

    my @range = @$inta;
    @excl = rangeSort(@excl);
    @excl = rangeMerge(@excl);

    for my $excl_ref (@excl) {
	my ($ea, $eb) = @$excl_ref;
	my @a = ();
	for my $range_ref (@range) {
	    my ($ra, $rb) = @$range_ref;
	    if      ($ea <= $ra) {
		if      ($eb <= $ra) { # no overlap, test next excl
		    push @a, $range_ref;
		} elsif ($eb <  $rb) { # overlaps left side of range
		    my $rest = [ $eb, $rb ];
		    push @a, $rest;
		} else { # total overlap, drop this range
		}
	    } elsif ($ea <  $rb) {
		if ($eb < $rb) { # overlap in the middle, split range in two parts
		    my $first = [ $ra, $ea ];
		    my $rest  = [ $eb, $rb ];
		    push @a, $first, $rest;
		} else { # right side overlap of range, save first part
		    my $first = [ $ra, $ea ];
		    push @a, $first;
		}
	    } else { # $ea >= $rb
		push @a, $range_ref;
	    }
	}
	@a = rangeSort(@a);
	@range = rangeMerge(@a);
    }
    @range;
}

sub in_angle($$$) {
    my $sta = shift; # start angle:   0 <= $sta <  360
    my $end = shift; # end angle:          $sta <= $end
    my $tst = shift; # angle to test: 0 <= $tst <  360
    my $ret = 0;

    if ($end < 360) {
	if ($sta <= $tst && $tst <= $end) { $ret = 1; }
    } else {
	if ($sta <= $tst || $tst <= $end) { $ret = 1; }
    }
    $ret;
}
sub silkCircleOblong2($$$$) {
    my $cr = shift;
    my $dim = shift;
    my $min = shift;
    my $max = shift;

    my @delta = ();
    if (-$cr <= $dim && $dim <= $cr) { # touches a side of the bounding box
	my $delta = triangle_x($cr, $dim);
	if ($min <= -$delta && -$delta <= $max) {
	    push @delta, -$delta;
	}
	if ($min <= $delta && $delta <= $max) {
	    push @delta, $delta;
	}
    }

    @delta;
}
sub silkCircleOblong($$$@) {
    my $pos = shift;
    my $cr  = shift;
    my $bb = shift; # bounding box
    my @excl = @_; # angle ranges to be excloded from the circle

    my ($cx, $cy) = @$pos;
    my ($xmin, $xmax, $ymin, $ymax) = @$bb;
    my ($tx, $TX, $ty, $TY) = ($xmin - $cx, $xmax - $cx, $ymin - $cy, $ymax - $cy); # here circle center at origo

#    print "\n";
#    print " cx $cx  cy $cy cr $cr\n";
#    print " xmin $xmin, xmax $xmax, ymin $ymin, ymax $ymax\n";
#    print " tx $tx, TX $TX, ty $ty, TY $TY\n";
    if ($tx <= -$cr && $cr <= $TX && $ty <= -$cr && $cr <= $TY) {
	# silk circle totally inside
	@excl = ([0,360]);
    } else {
	my @lft = silkCircleOblong2($cr, $tx, $ty, $TY); # touches left side
	my @bot = silkCircleOblong2($cr, $TY, $tx, $TX); # touches bottom side
	my @rht = silkCircleOblong2($cr, $TX, $ty, $TY); # touches right side
	my @top = silkCircleOblong2($cr, $ty, $tx, $TX); # touches top of bbox

	# translate back and make them doordinates
	@lft = map { [ $tx, $_ ] } @lft;
	@bot = map { [ $_, $TY ] } @bot;
	@rht = map { [ $TX, $_ ] } @rht;
	@top = map { [ $_, $ty ] } @top;
	# convert to angles
	@lft = map { round(PcbAnglev($_), 0.1); } @lft;
	@bot = map { round(PcbAnglev($_), 0.1); } @bot;
	@rht = map { round(PcbAnglev($_), 0.1); } @rht;
	@top = map { round(PcbAnglev($_), 0.1); } @top;
	#
	@lft = sort { $a <=> $b } @lft;
	@bot = sort { $a <=> $b } @bot;
	@rht = sort { $a <=> $b } @rht;
	@top = sort { $a <=> $b } @top;

	my @min;
	if (@lft) {
	    if ($lft[0] == 0 || $lft[0] == 180) { # tangential touches doesn't affect @excl
		@lft = ();
	    } else {
		my $dir;
		if ( 0 < $lft[0] && $lft[0] <  180) {
		    $dir = "I";
		} else {
		    $dir = "O";
		}
		@min = ( $lft[0], $dir );
	    }
	}
	if (@bot) {
	    if ($bot[0] == 90 || $bot[0] == 270) {
		@bot = ();
	    } else {
		my $dir;
		if ( 90 < $bot[0] && $bot[0] <  270) {
		    $dir = "I";
		} else {
		    $dir = "O";
		}
		if (@min == 0 || $bot[0] < $min[0]) {
		    @min = ( $bot[0], $dir );
		}
	    }
	}
	if (@rht) {
	    if ($rht[0] ==  0 || $rht[0] == 180) {
		@rht = ();
	    } else {
		my $dir;
		if (  0 < $rht[0] && $rht[0] <  180) {
		    $dir = "O";
		} else {
		    $dir = "I";
		}
		if (@min == 0 || $rht[0] < $min[0]) {
		    @min = ( $rht[0], $dir );
		}
	    }
	}
	if (@top) {
	    if ($top[0] == 90 || $top[0] == 270) {
		@top = ();
	    } else {
		my $dir;
		if ( 90 < $top[0] && $top[0] <  270) {
		    $dir = "O";
		} else {
		    $dir = "I";
		}
		if (@min == 0 || $top[0] < $min[0]) {
		    @min = ( $top[0], $dir );
		}
	    }
	}

	my @ang = sort { $a <=> $b } (@lft, @bot, @rht, @top);
	if (@min && $min[1] eq "O" ) {
	    my $ang = shift @ang;
	    push @ang, $ang;
	}
	if (@ang % 2) {
	    print "in bb_2d(): ERR uneven # of elements:\n \@arg = ( ", join(", ", @ang), " )\n";
	}

	while (@ang) {
	    my $a = shift @ang;
	    my $b = shift @ang;
	    if ($b < $a) {
		$b += 360;
	    }
	    push @excl, [ $a, $b ];
	}
	@excl = rangeWrap(360, @excl);
    }
    @excl;
}
sub silkCircleCircle($$$@) {
    my $pos = shift;
    my $r = shift;
    my $bb = shift;
    my @excl = @_;

    my ( $xmin, $xmax, $ymin, $ymax, $pin_no, $bbr ) = @$bb;
    my $xw = $xmax-$xmin;
    my $yw = $ymax-$ymin;
    my $width = $xw < $yw ? $xw : $yw;

    my $bbpos = [ $xmin + $xw/2, $ymin + $yw/2 ];
    my $pd = vec_distance($pos, $bbpos);
    #print " r $r  bbr $bbr  pd $pd\n";
    if ($pd >= $r + $bbr) {	# no contact, ignore this bb
	#print "cirlce A\n";
    } elsif ($r >= $pd + $bbr) { # no contact, ignore this bb
	#print "cirlce B\n";
    } elsif ($bbr >= $pd + $r) { # silk inside pad/pin
	#print "cirlce C\n";
	@excl = ([0,360]);
    } elsif ($pd <= 0) {	     # same center
	#print "cirlce D\n";
	if ($r < $bbr) {	# silk completely covered by bb
	    @excl = ([0,360]);
	} else {	       # this bb doesn't affect the circle/arc
	}
    } else {  # silk and pad/pin centers are apart
	#print "cirlce E\n";
	# use cosine law: a^2 = b^2 + c^2 - 2*b*c * cos( alpha )
	my $csa = ( $r*$r + $pd*$pd - $bbr*$bbr ) / (2*$r*$pd);
	my $da = round(Acos($csa),0.1);
	my $a  = round(PcbAnglev(vec_sub($bbpos, $pos)), 0.1);
	#print " csa $csa  ds $da  a $da\n";
	#print "pre: "; print Dumper(\@excl);
	push @excl, [ $a - $da, $a + $da ];
	#print "B  : "; print Dumper(\@excl);
	@excl = rangeWrap(360, @excl);
    }
    @excl;
}
#sub silk_circle_testing() {
#    element_start("a.fp", "", "test", "M?", 100);
#    $round_first_pin = 1;
#    pin( 0, 0, 1.0, 2);
#    #pin(  1, 0, 0.5, 1);
#    #pad(0,0, 0.70, 3.20,  "die heatsink", "", 0, 0);
#    my @bbw = bb_enlarge($silk_w/2, @bounding_box);
#    for (my $ix = -3; $ix <= 3; $ix += 0.25) {
#	for (my $iy = -3; $iy <= 3; $iy += 0.25) {
#	    #my $iy = -0.2;
#	    silk_circle([$ix,$iy], 1, 0, 360, \@bbw);
#	}
#    }
#    element_stop();
#}
#silk_circle_testing();
sub silk_circle($$ ; $$$) {
    my $pos = shift;
    my $r = shift;

    my $sta   = shift;	 # sta = 0 => left, 90 down, 180 right, 270 up
    my $sweep = shift;
    my $bb    = shift;

    # normalize the angles
    if (!defined($sta)) {
	$sta = 0;
    }
    if (!defined($sweep) || $sweep >= 360 || $sweep <= -360) {
	$sta = 0;
	$sweep = 360;
    }
    # now -360 < sweep <= 360

    # make sure both sta and sweep are positive
    if ($sweep < 0) {
	$sta = $sta + $sweep;
	$sweep = - $sweep;
    }
    $sta = deg_normalize($sta);

    my $xx = mk_mm($$pos[0]);
    my $yy = mk_mm($$pos[1]);
    my $rr = mk_mm($r);
    if (!defined($bb)) {
	pr "ElementArc  [ $xx $yy  $rr $rr  $sta $sweep $silk_width]\n";
    } else {
	#my $end = $sta + $sweep;
	# get bounding box of arc, as if it has a radius of 1 with center in origin
	# Note: in geda angle 0 == straight left

	my $box = bb_OfAnArc($pos, $r, $sta, $sweep);
	my @bb = @$bb;
	@bb = grep { $$_[0] <= $$box[1] && $$box[0] <= $$_[1] } @bb;
	@bb = grep { $$_[2] <= $$box[3] && $$box[2] <= $$_[3] } @bb;

	@bb = bb_sort(@bb);
	#	bb_show(@bb);
	my $end = $sta+$sweep;
	my @arc = ( [$sta, $end] );
	my $inside = 0;
	my @excl = ();

	for my $bbe (@bb) {
	    my ( $xmin, $xmax, $ymin, $ymax, $pin_no, $bbr ) = @$bbe;
	    my $xw = $xmax-$xmin;
	    my $yw = $ymax-$ymin;
	    my $width = $xw < $yw ? $xw : $yw;

	    if ($bbr <= 0) {	# rectangle with sharp corners
		#print "Rect\n";
		# won't happen, a rect. pad+mask_gap will have rounded corners with radi = silk_width/2
	    } elsif ($bbr < $width * 0.48 ) { # rectangle with rounded corners
		#print "Oblong\n";
		@excl = silkCircleOblong($pos, $r, $bbe, @excl);
	    } else {		# circle/arc
		#print "Circle\n";
		@excl = silkCircleCircle($pos,$r,$bbe,@excl);
	    }
	}
	if (@excl) {
	    @excl = rangeSort(@excl);
	    @arc = rangeExcl(@arc, @excl);
	}
	for my $arc (@arc) {
	    my ($Sta,$End) = @$arc;
	    my $Sweep;
	    if ($Sta <= $End) {
		$Sweep = $End - $Sta;
	    } else {
		$Sweep = $End+360 - $Sta;
	    }
	    my $prSta = sprintf("%6.1f", $Sta);
	    my $prSweep = sprintf("%6.1f", $Sweep);
	    pr "ElementArc  [ $xx $yy  $rr $rr  $prSta $prSweep $silk_width]\n";
	}
    }
}

sub silk_arc($$$$ ; $) { # same as silk_circle but sta/sweep not optional
    my $pos = shift;
    my $r = shift;
    my $sta   = shift; # sta = 0 => left, 90 down, 180 right, 270 up
    my $sweep = shift;
    my $bb = shift;

    silk_circle($pos, $r, $sta, $sweep, $bb);
}

sub silk_circle_segment($$$$) {
    my $pos = shift;
    my $r = shift;
    my $s = shift; # center to flat distance <= $r
    my $a = shift; # flat center pointing at this angle

    my $b = int(rad_deg(acos($s/$r)));
    my $bs = $a + $b;
    my $be = $a - $b;

    $bs = deg_rad($bs);
    $be = deg_rad($be);

    my $x1 = mk_mm($$pos[0] - $r*cos($bs));
    my $y1 = mk_mm($$pos[1] + $r*sin($bs));

    my $x2 = mk_mm($$pos[0] - $r*cos($be));
    my $y2 = mk_mm($$pos[1] + $r*sin($be));
    pr "ElementLine [ $x1 $y1  $x2 $y2   $silk_width]\n";
}

sub silk_circle_flat($$$$;$) {
    my $pos = shift;
    my $r = shift;
    my $s = shift; # center to flat distance <= $r
    my $a = shift; # flat center pointing at this angle
    my $bb = shift;

    my $b = int(rad_deg(acos($s/$r)));
    my $bs = $a + $b;
    my $be = $a - $b;
    my $bt = 360 - 2*$b;

    silk_circle($pos, $r, $bs, $bt, $bb);
    {
	$bs = deg_rad($bs);
	$be = deg_rad($be);

	my $x1 = $$pos[0] - $r*cos($bs);
	my $y1 = $$pos[1] + $r*sin($bs);

	my $x2 = $$pos[0] - $r*cos($be);
	my $y2 = $$pos[1] + $r*sin($be);
	silk_start($x1, $y1);
	silk_line_bb($x2, $y2, $bb);
	#pr "ElementLine [ $x1 $y1  $x2 $y2   $silk_width]\n";
    }
}

sub silk_circle_tab($$$$$) {
    my $pos = shift;
    my $r = shift;
    my $e = shift; # circle to tab end distance
    my $w = shift; # width of tab
    my $a = shift; # tab angle, its direction

    if ($w > 2*$r) {
	warn("silk_circle_tab([$$pos[0],$$pos[1]], $r, $e, $w, $a): too wide tab");
	$w = 2*$r;
    }
    #print("silk_circle_tab([$$pos[0],$$pos[1]], $r, $e, $w, $a)\n");

    my $b = int(rad_deg(asin(($w/2)/$r)));
    my $bs = $a + $b;
    my $be = $a - $b;
    my $bt = 360 - 2*$b;
    {
	my $x = mk_mm($$pos[0]);
	my $y = mk_mm($$pos[1]);
	my $rr = mk_mm($r);
	pr "ElementArc  [ $x $y  $rr $rr  $bs $bt $silk_width]\n";
    }
    {
	$bs = deg_rad($bs);
	$be = deg_rad($be);
	my $v = polar_vec([1, deg_rad($a)]); # unit vector in tab direction
	#print "v[ $$v[0], $$v[1] ], $a\n";
	my $psta = [ $$pos[0] - $r*cos($bs), $$pos[1] + $r*sin($bs) ];
	my $pend = [ $$pos[0] - $r*cos($be), $$pos[1] + $r*sin($be) ];
	my $p1 = vec_add($psta, vec_mul($e, $v));
	my $p2 = vec_add($pend, vec_mul($e, $v));

	silk_vstart($psta);
	silk_vline ($p1);
	silk_vline ($p2);
	silk_vline ($pend);
    }
}

sub silk_circle_notch($$$$;$) {
    my $pos = shift;
    my $r = shift;
    my $nb = shift; # center to notch bottom <= $r
    my $nw = shift; # notch witdh

    my $a = shift; # notch pointing at this angle
    if (!defined($a)) { $a = -90; } # up

    my $b = rad_deg(asin($nw/$r/2));
    my $bs = $a + $b;
    my $be = $a - $b;
    my $bt = 360 - 2*$b;
    {
	my $x = mk_mm($$pos[0]);
	my $y = mk_mm($$pos[1]);
	my $rr = mk_mm($r);
	pr "ElementArc  [ $x $y  $rr $rr  $bs $bt $silk_width]\n";
    }
    {
	$bs = deg_rad($bs);
	$be = deg_rad($be);

	my $x1 = $$pos[0] - $r*cos($bs);
	my $y1 = $$pos[1] + $r*sin($bs);

	my $x2 = $$pos[0] - $r*cos($be);
	my $y2 = $$pos[1] + $r*sin($be);

	#printf "%.2f %.2f\n", $nb, $a;
	my $nc = polar_vec([$nb, deg_rad($a)]);
	my $Nw = vec_normal(polar_vec([$nw/2, deg_rad($a)]));
	my $na = vec_add($nc, $Nw);
	my $nb = vec_sub($nc, $Nw);

	silk_start($x1, $y1);
#	silk_vline($nc);
	silk_vline($nb);
	silk_vline($na);
#	silk_vline($origin);
	silk_line($x2, $y2);
    }
}

sub silk_bb(;$) {
  my $w = shift;
  if (!defined($w)) { $w = $silk_default; }

  if (!defined($bbx1)) { return; }

  my $x1 = mk_mm($bbx1-$w/2);
  my $x2 = mk_mm($bbx2+$w/2);
  my $y1 = mk_mm($bby1-$w/2);
  my $y2 = mk_mm($bby2+$w/2);
  #my $x1 = mk_mm($bbx1 - $w/2);
  #my $x2 = mk_mm($bbx2 + $w/2);
  #my $y1 = mk_mm($bby1 - $w/2);
  #my $y2 = mk_mm($bby2 + $w/2);
  $w = mk_mm($w);
  #pr "ElementLine [ 0 0 0 -2mm  $w ]\n";

  pr "ElementLine [ $x1 $y1 $x2 $y1  $w ]\n";
  pr "ElementLine [ $x2 $y1 $x2 $y2  $w ]\n";
  pr "ElementLine [ $x2 $y2 $x1 $y2  $w ]\n";
  pr "ElementLine [ $x1 $y2 $x1 $y1  $w ]\n";
}

########################################

sub iterate_fdxy( & @ ) {
    # @ARGV = ( func, ( [ data, [ x... ], [ y... ] ], ...) )
    # run for &$func( [x, y1], data), &$func( [x, y2], data), ...
    my $func = shift;

    for my $r (@_) {
	my @arr = @$r;
	#next if (@arr < 3);
	my $data = shift @arr;
	my $xr = shift @arr;
	my $yr = shift @arr;
	for my $x (@$xr) {
	    for my $y (@$yr) {
		if ($y) {
		    if ($x) { &$func( [-$x, -$y], $data); }
		    &$func( [$x, -$y], $data );
		}
		if ($x) { &$func( [-$x, $y], $data); }
		&$func( [$x, $y], $data);
	    }
	}
    }
}

sub iterate_y_xxx( & $ ) {
    # $r = [ y, x1, x2, ... ], run for &$func( x1, y), &$func( x2, y), ...
    my $func = shift;
    my $r = shift;
    my @arr = @$r;

    return if (@arr < 1);
    my $y = shift @arr;
    for my $x (@arr) {
	&$func( $x/2, $y/2);
	if ($y) {
	    &$func( $x/2, -$y/2);
	}
	if ($x) {
	    &$func( -$x/2, $y/2);
	    if ($y) {
		&$func( -$x/2, -$y/2);
	    }
	}
    }
}

sub iterate_fdyxxx( @ ) {
    # @ARGV = ( func, [ data, y, x1, x2, ... ], ... )
    # run for &$func( data, x1, y), &$func( data, x2, y), ...
    my $func = shift;

    for my $r (@_) {
	my @arr = @$r;
	next if (@arr < 3);
	my $data = shift @arr;
	my $y = shift @arr;
	for my $x (@arr) {
	    &$func( $data, $x, $y);
	    if ($y) { &$func( $data, $x, -$y); }
	    if ($x) {
		&$func( $data, -$x, $y);
		if ($y) { &$func( $data, -$x, -$y); }
	    }
	}
    }
}

########################################
## Through hole footprints #############
########################################

# manual testing:
# 1.1 .23x1.07/1.02
# 0.9 .75 .78 .8
# 0.8 .35x.75
# 0.7 .5x.5 .55 .58 .6
# .6/.7 .38x.42
# 0.6 .5
# .5/.6 .28x.45
# .5 .35
sub calc_samtec() {
    my $lead_drill_samtec =
# https://www.samtec.com/support/pcb-hole-sizes
#  Lead Size 	Hole Size
" (0.46) .018 Dia. 	(0.61) .024 Dia.
 (0.51) .020 Dia. 	(0.66) .026 Dia.
 (0.64) .025 Dia. 	(0.79) .031 Dia.
 (0.76) .030 Dia. 	(0.91) .036 Dia.
 (0.89) .035 Dia. 	(1.04) .041 Dia.
 (1.14) .045 Dia. 	(1.30) .051 Dia.
 (1.32) .052 Dia. 	(1.47) .058 Dia.
 (0.30) .012 Sq. 	(0.56) .022 Dia.
 (0.41) .016 Sq. 	(0.71) .028 Dia.
 (0.46) .018 Sq. 	(0.76) .030 Dia.
 (0.51) .020 Sq. 	(0.81) .032 Dia.
 (0.64) .025 Sq. 	(1.02) .040 Dia.
 (1.14) .045 Sq. 	(1.75) .069 Dia.
 (0.13) .005 x (0.41) .016 	(0.56) .022 Dia.
 (0.20) .008 x (0.71) .028 	(0.89) .035 Dia.
 (0.25) .010 x (0.36) .014 	(0.56) .022 Dia.
 (0.25) .010 x (0.51) .020 	(0.71) .028 Dia.
 (0.41) .016 x (0.51) .020 	(0.79) .031 Dia.
 (0.41) .016 x (0.61) .024 	(0.89) .035 Dia.
 (0.41) .016 x (0.79) .031 	(1.04) .041 Dia.
";
    my @dia;
    my @drill;
    for (split(/\n/, $lead_drill_samtec)) {
	chomp;
	my $dia = 0;
	my $drill = 0;
	if (m/\((\d\.\d+)\).*(Dia.|Sq.).*\((\d\.\d+)\)/) {
	    my $lead = $1;
	    $drill = $3;
	    my $type = $2;
	    if ($type eq "Sq.") {
		$dia = sqrt(2)*$lead;
		#next;
	    } else {
		$dia = $lead;
	    }
	    print "$lead: $drill / $type / $dia\n";
	    push @dia, $dia;
	    push @drill, $drill;
	} elsif (m/\((\d\.\d+)\).*x.*\((\d\.\d+)\).*\((\d\.\d+)\)/) {
	    #next;
	    my $x = $1;
	    my $y = $2;
	    $drill = $3;
	    $dia = triangle_r($x,$y);
	    print "$x x $y: $drill / $dia\n";
	    push @dia, $dia;
	    push @drill, $drill;
	}
    }
    my ($a0, $a1) = stat_linreg(\@dia, \@drill);
    printf ("%.3f %.3f\n", $a0, $a1);
    for (my $ix = 0; $ix < @dia; $ix++) {
	my $drill = $a0 + $a1 * $dia[$ix];
	my $err =  $drill - $drill[$ix];
	printf "%.2f %.2f %.2f %.2f\n", $dia[$ix], $drill[$ix], $drill, $err;
    }
    # only round leads: 0.147 1.005
    # all included    : 0.130 1.011
}
#calc_samtec();

# might be slightly tight, if you want looser fit add 0.1mm to drill
sub lead_to_drill($ ; $) {
    my $lead_dia = shift;
    my $w = shift; # i.e. a rect. pin of size $lead_dia x $w
    if (defined($w) && $w != 0) { $lead_dia = sqrt($w * $w + $lead_dia * $lead_dia); }

    # http://aqdi.com/articles/electronics-design-checklist-3/ point 2:
    #  wants $drill >= $lead + 10mils (.254mm)
    # IPC seems to say 0.15, 0.20 and 0.25
    # first approx., have to test with different leads
    my $drill = 0.2 + int(1.01 * $lead_dia * 10 + 0.9) / 10; # round up
    #print("$lead_dia -> $drill\n");
    $drill;
}
sub show_lead2drill() {
    for (my $lead = 0.4; $lead < 2; $lead += 0.1) {
	my $drill = lead_to_drill($lead);
	my $diff = $drill - $lead;
	printf("%.2f %.2f %.2f\n", $lead, $drill, $diff);
    }
}
#show_lead2drill();

sub curve($@) {
    my $x = shift;
    my @a = @_;

    my $y = $a[0];
    my $xx = $x;
    for (my $ax = 1; $ax < @a; $ax++) {
	$y += $a[$ax] * $xx;
	$xx *= $x;
    }
    $y;
}

sub drill_to_cudia( $ ) {
    # http://aqdi.com/articles/electronics-design-checklist-3/ p.2 says +15mil (0.4mm)
    # some generic cu dia to start with
    my $drill = shift;
    0.3 + int(10 * $drill * 1.7 + 0.5) / 10;
}
sub thickness_suffix( $ ) {
    my $ix = shift;
    if ($thickness_as_digit) {
	return $ix;
    } else {
	return $thickness_suffix[$ix];
    }
}
sub drill2thickness( $ ) {
    my $drill = shift;

    my $r = $drill2thickness{$drill};
    if (defined($r)) { return @$r; }

    my @res;
    for ( my $ix = 0; $ix < @drill2thickness; $ix++) {
	my @arr = @{$drill2thickness[$ix]};
	my $y = curve($drill, @arr);
	$y = roundup($y, 0.1);
	push @res, $y;
    }
    $drill2thickness{$drill} = [ @res ];
    @res;
}
sub show_thickness() {
    print "hole/sz";
    for (my $ix = 0; $ix < @drill2thickness; $ix++) {
	printf " %5s", $ix;
    }
    print "\n";
    for (my $drill = 0.3; $drill < 5; $drill += 0.1) {
	printf "%5.1f  ", $drill, ;
	my @arr = drill2thickness($drill);
	for (my $ix = 0; $ix < @arr; $ix++) {
	    printf " %5.1f", $arr[$ix];
	}
	print "\n";
	#last;
    }
}
#show_thickness();

##############################
# axial types

sub ipc_bend($$) {
    # http://www.ipc.org/committee/drafts/1-13_d_7251WD1.pdf p. 12, Table 3-1, Fig. 3-5 p11 is different
    # not clear what is what, need to get the real standard ducumentation
    my $lead_dia = shift;
    my $level = shift;
    my %lvl = ( "A" => 0, "B" => 1, "C" => 2 );
    my $ix = $lvl{$level};
    if (!defined($ix)) { $ix = 0; };
    my @s;
    my $r;

    if      ($lead_dia < 0.85) {
	@s = (1.2, 1.0, 0.8);
	$r = 1;
    } elsif ($lead_dia < 1.25) {
	@s = (2.2, 1.8, 1.5);
	$r = 1.5;
    } else {
	@s = (2.8, 2.4, 2.0);
	$r = 2.0;
    }
    my $lead_min = ($s[$ix] + $r) * $lead_dia;

    $lead_min;
}
sub gen_axial($$$ ; $$) {
    my $name = shift;
    my $doc  = shift;
    my $dim = shift;

    my $mark     = shift;
    my $pin_name = shift;


    if (!defined($$dim[3])) { $$dim[3] = 25; }
    if (!defined($$dim[4])) { $$dim[4] =  2; }
    my ( $body_D, $lead_dia, $body_L, $lead_length, $lead_min ) = @$dim;

    if (!defined($mark)) { $mark = []; }
    if (!defined($pin_name)) { $pin_name = [ "", "" ]; }

    my $drill = lead_to_drill($lead_dia);
    my @thickness = drill2thickness($drill);

    $pr_save = "";
    pr_inc();
    if (@$mark) {
	# mark is always on pin 1 here (my convention)
	my @arr = @$mark;
	my $type = $$mark[0];

	pr("  # body\n");
	if ($type eq "line") {
	    silk_crect([0,0], [$body_L, $body_D], 0);
	    pr("  # mark\n");
	    my $sta = 0.8;
	    my $end = 0.5;
	    $sta = - int( 10 * $sta * $body_L / 2) / 10;
	    if ($sta < -$body_L/2 + $silk_w) {
		$sta = -$body_L/2 + 1.5 * $silk_w;
	    }
	    $end = - $end * $body_L / 2;
	    my $step = int( 10 * $silk_w * 0.9 + 0.5) / 10;
	    silk_start( $sta, $body_D/2);
	    silk_rline(  0, -$body_D);
	    for (my $L = $sta+$step; $L < $end; $L += $step) {
		silk_start( $L, $body_D/2);
		silk_rline(  0, -$body_D);
	    }
	} elsif ($type eq "bevel") {
	    my $L = $arr[1];
	    silk_start(-$body_L/2   , -$body_D/2+$L);
	    silk_line (-$body_L/2+$L, -$body_D/2);
	    silk_line ( $body_L/2   , -$body_D/2);
	    silk_line ( $body_L/2   ,  $body_D/2);
	    silk_line (-$body_L/2+$L,  $body_D/2);
	    silk_line (-$body_L/2   ,  $body_D/2-$L);
	    silk_line (-$body_L/2   , -$body_D/2+$L);
	    silk_width(0.18);
	    silk_start(-$body_L/2+$L, -$body_D/2+2*$silk_w);
	    silk_line (-$body_L/2+$L,  $body_D/2-2*$silk_w);
	    silk_width();
    	} elsif ($type eq "ellyt") {
	} elsif ($type eq "ball") {
	} else {
	}
    } else {
	silk_crect([0,0], [$body_L, $body_D], 0);
    }
    pr_dec();
    my $body = $pr_save;
    my $hor_min = $body_L + 2*$lead_min;

    my @list;
    {
	# stadinng up
	my $step = 1;
	my $min = roundup($body_D, $step);
	my $max = int($hor_min);
	if ($max > $min + 5) { $max = $min + 5; }
	@list = ( $min .. $max );
	# laying down
	$step = 5;
	my $a = roundup($hor_min, 1);
	$min = roundup($hor_min, $step);
	if ($a < $min) { push @list, $a; } # make one laying down at minimum lead separation
	$max = rounddown(2*$lead_length+$body_L - $body_D/2 - 1.6 - 2, $step);
	for (my $spacing = $min; $spacing < $max; $spacing += $step) { push @list, $spacing; }
    }
    for my $spacing (@list) {
	for (my $ix = 0; $ix < @thickness; $ix++) {
	    my $file = sprintf("%s_%02d%s.fp", $name, $spacing, thickness_suffix($ix));
	    my $limit_radius = $thickness[$ix]/2 + $mask_gap;
	    if ($spacing/2 < $limit_radius) {
		#warn "$file: too close spacing <$spacing $limit_radius";
		next;
	    }
	    #print "$file\n";
	    $limit_radius += $silk_w/2;
	    my $xx = $spacing/2 - $limit_radius;

	    my $standing = $spacing < $hor_min;
	    my $str = $doc;
	    if ($standing) {
		$str .= "# the component is standing on pin 2 and the visible lead is bent over down to pin 1\n";
	    }
	    element_start($file, $str);

	    pin( -$spacing/2, 0, $drill, $thickness[$ix], $$pin_name[0] );
	    pin(  $spacing/2, 0, $drill, $thickness[$ix], $$pin_name[1] );

	    if ($standing) {
		my $bD = $body_D;
		if ($xx > 0) {
		    pr("  # the visible lead\n");
		    silk_start(-$xx, 0);
		    silk_line(  $xx, 0);
		}
		pr("  # body\n");
		if ($body_D/2 < $limit_radius) {
		    #print "$file: body_D enlarged $body_D $spacing\n";
		    $bD = 2*$limit_radius;
		}
		if ($bD/2 < $spacing/2 + $xx) {
		    silk_circle( [$spacing/2, 0],  $bD/2);
		} else {
		    my $a = $bD/2;
		    my $b = $limit_radius;
		    my $c = $spacing;
		    # cosinussatz
		    my $beta = acos( ($a*$a + $c*$c - $b*$b)/(2*$a*$c));
		    $beta = int(rad_deg($beta));
		    my $pos = [ $spacing/2, 0 ];
		    silk_circle($pos, $bD/2, $beta, 360 - 2*$beta);
		}
	    } else {
		if ($xx > $body_L/2) {
		    pr($body,1);
		    if ($body_L/2 < $xx) {
			pr("  # leads\n");
			silk_start(-$xx, 0);
			silk_line(-$body_L/2, 0);
			silk_start($xx, 0);
			silk_line($body_L/2, 0);
		    }
		}
	    }
	    element_stop();
	}
    }
}
sub gen_axial_list(@) {
    for my $r (@_) {
	my ($name, $doc, $dim, $mark, $pin_name) = @$r;
	gen_axial($name, $doc, $dim, $mark, $pin_name);
    }
}
sub gen_axial_diodes(@) {
    for my $r (@_) {
	my ($name, $doc, $dim, $mark, $pin_name ) = @$r;
	if (!defined($mark    )) { $mark     = [ "line"             ]; }
	if (!defined($pin_name)) { $pin_name = [ "Cathode", "Anode" ]; }
	gen_axial($name, $doc, $dim, $mark, $pin_name);
    }
}

sub gen_littlefuse_cg() {
    my $name = "Littlefuse_CGxxLTR";
    my $doc = "# http://www1.elfa.se/data1/wwwroot/assets/datasheets/cg_cg2-series_eng_tds.pdf\n";
    # no reason to have long leads for a gas discharge tube
    my $dim = [ 8.1, 0.81, 6.07, (30 - 6)/2, 2 ]; # $body_D, $lead_dia, $body_L, $lead_length, $lead_min
    gen_axial($name, $doc, $dim);
}
#gen_littlefuse_cg();

sub gen_TE_LR() {
    my $prefix = "TE";

    my @tp1h = qw/ W % ppm V /;
    my @tp1 = (
	# LR0204  LR1L         LR1       LR2        LR100        LR200
	[   0.25,  0.5,        0.6,     0.75,           1,           2, ], # W
	[      1,    5, "0.5 to 5", "1 to 2",    "1 to 5",    "1 to 5", ], # %
        [    100,  200,   "50/100",      100, "25/50/100", "25/50/100", ], # ppm
	[    200,  350,        350,      350,         500,         500, ], # V
    );

    my @tp3h =
	qw/name       L    D    d    l/;
    my @tp3 = ( # table on page 2
	[ "LR0204",  3.5, 2.0, 0.45, 28 ],
	[ "LR1"   ,  6.2, 2.3, 0.55, 28 ],
	[ "LR1L"  ,  6.2, 2.3, 0.55, 28 ],
	[ "LR2"   ,  9.7, 3.5, 0.55, 28 ],
	[ "LR100" , 12.0, 5.0, 0.7 , 28 ],
	[ "LR200" , 12.0, 5.5, 0.7 , 28 ],
       #[ "MF0204",  3.4, 1.9  0.45, 28 ], Yageo
       #[ "MF0207",  6.3, 2.4, 0.55, 28 ], Yageo
    );

    $round_first_pin = 1;
    for (my $ix = 0; $ix < @tp3; $ix++) {
	my $str = "";
	for (my $sx = 0; $sx < @tp1; $sx++) {
	    $str .= " " . $tp1[$sx][$ix] . $tp1h[$sx];
	}
	my $doc = "# TE type LR series Metal Film Fixed Resistors
#$str
# http://www.farnell.com/datasheets/1723855.pdf
";
	my ($name, $body_L, $body_D, $lead_dia, $lead_length) = @{$tp3[$ix]};
	my $dim = [ $body_D, $lead_dia, $body_L, $lead_length ];
	gen_axial("\L${prefix}_$name", $doc, $dim);
    }
    $round_first_pin = 0;

}
#gen_TE_LR();

sub gen_DiodesCom() {
    my @arr = (
	# name, doc, [  body_dia, lead_dia (max), body_length, lead_length, ], mark
	[
	 "bcd_DO-15",
	 "# https://www.diodes.com/assets/Diodes-Packaging/Mechanical-Dimensions-BCD.pdf p.138\n\n",
	 [ (2.60+3.60)/2, 0.9, (5.8+7.6)/2, 25.4, ]
	],
	[
	 "bcd_DO-27",
	 "# https://www.diodes.com/assets/Diodes-Packaging/Mechanical-Dimensions-BCD.pdf p.234\n\n",
	 [ (5.00+5.60)/2, 1.3, (8.5+9.5)/2, 25.4, ]
	],
	[
	 "bcd_R-1",
	 "# https://www.diodes.com/assets/Diodes-Packaging/Mechanical-Dimensions-BCD.pdf p.245\n\n",
	 [ (2.20+2.60)/2, 0.64, (2.9+3.5)/2, 20.0, ]
	],
	[
	 "diodes_DO-15",
	 "# https://www.diodes.com/assets/Package-Files/DO-15.pdf\n\n",
	 [ (2.60+3.60)/2, 0.889, (5.5+7.62)/2, 25.4, ]
	],
	[
	 "diodes_DO-201AD",
	 "# https://www.diodes.com/assets/Package-Files/DO-201AD.pdf\n\n",
	 [ (4.80+5.30)/2, 1.30, (7.20+9.50)/2, 25.4, ]
	],
	[
	 "diodes_DO-201",
	 "# https://www.diodes.com/assets/Package-Files/DO-201.pdf\n\n",
	 [ (4.80+5.21)/2, 1.06, (8.50+9.53)/2, 25.4, ]
	],
	[
	 "diodes_DO-35",
	 "# https://www.diodes.com/assets/Package-Files/DO-35.pdf\n\n",
	 [ 2.0, 0.6, 4, 25.4, ]
	],
	[
	 "diodes_DO-41-Glass",
	 "# https://www.diodes.com/assets/Package-Files/DO-41-Glass.pdf\n\n",
	 [ 2.71, 0.863, 4.7, 25.4, ]
	],
	[
	 "diodes_DO-41-Plastic",
	 "# https://www.diodes.com/assets/Package-Files/DO-41-Plastic.pdf\n\n",
	 [ (2.00+2.72)/2, 0.864, (4.0+5.21)/2, 25.4, ]
	],
    );
    gen_axial_diodes(@arr);
}
#gen_DiodesCom();

sub gen_jedec_DO204() {
    # jedec designation / wikipedia des. / description
    # øb = C = lead dia
    # øD = D = body dia
    # G  = B = body length
    # L  = A = lead length
    # L1 = E = initial lead length
    # table below is from https://en.wikipedia.org/wiki/DO-204
#Variant Other standards A 		B 		C 		D 		E
#			min 	max 	min 	max 	min 	max 	min 	max 	min 	max
    my $str =
"AA 	DO-7 [3] 	25.40 	38.10 	5.85 	7.65 	0.46 	0.55 	2.16 	2.71 	— 	1.27
AB 	DO-14 [4] 	25.40 	38.10 	5.85 	7.62 	0.46 	0.55 	2.75 	3.55 	— 	1.27
AC 	DO-15 [5] 	25.40 	38.10 	5.85 	7.62 	0.69 	0.88 	2.65 	3.55 	— 	1.27
AD 	DO-16 [6] 	11.43 	19.05 	1.27 	2.54 	0.23 	0.33 	— 	1.27 	— 	1.27
AE 	DO-26 [7] 	35.56 	38.10 	8.75 	10.41 	0.69 	0.99 	5.59 	6.60 	— 	2.03
AF 	DO-29 [8] 	25.40 	38.10 	8.00 	9.14 	0.74 	0.83 	3.05 	3.81 	— 	1.27
AG 	DO-34 [9] 	25.40 	38.10 	2.16 	3.04 	0.46 	0.55 	1.27 	1.90 	— 	1.27
AH 	DO-35 [10] 	25.40 	38.10 	3.05 	5.08 	0.46 	0.55 	1.53 	2.28 	— 	1.27
AJ 	— 		11.43 	13.97 	5.85 	7.62 	0.49 	0.53 	2.16 	2.66 	— 	1.27
AK 	— 		11.43 	13.97 	3.81 	4.45 	0.36 	0.40 	1.66 	1.90 	— 	1.27
AL 	DO-41 [11] 	25.40 	— 	4.07 	5.20 	0.72 	0.86 	2.04 	2.71 	— 	1.27
AM 	— 		17.53 	38.10 	3.18 	5.20 	0.64 	0.91 	1.27 	2.79 	— 	1.27
AN 	— 		25.40 	— 	5.08 	5.84 	0.71 	0.86 	2.54 	3.05 	— 	1.27
AP 	— 		25.40 	38.10 	3.18 	4.57 	0.74 	0.89 	2.54 	3.81 	— 	1.27
AR 	— 		27.95 	38.10 	9.27 	9.52 	1.22 	1.32 	6.10 	6.35 	— 	2.54
";
    $str =~ s/\[\d+\]//g;
    $str =~ tr/ \t\r/\t/s;
    $str =~ tr/—/-/;
    my @line = split(/\n/, $str);
    for (@line) {
	chomp;
	my @fld = split;
	my $suffix = $fld[0];
	my $alt    = $fld[1];
	my $lead_length = $fld[2]; # L / A, use min
	my $body_L = ($fld[4] + $fld[5])/2; # G / B
	my $lead_dia = $fld[7]; # øb / C, use max
	my $body_D = $fld[8] eq "-" ? $fld[9] : ($fld[8] + $fld[9])/2; # øD / D

	my $name = "jedec_DO-204-$suffix";
	my $doc =
"# http://www.jedec.org/ DO-204B-D.PDF
# https://en.wikipedia.org/wiki/DO-204
";
	if ($alt) {
	    $doc .= "# also know as $alt\n";
	}
	my $dim = [ $body_D, $lead_dia, $body_L, $lead_length, ];
	my $mark     = [ "line"             ];
	my $pin_name = [ "Cathode", "Anode" ];
	gen_axial($name, $doc, $dim, $mark, $pin_name);
    }
}
#gen_jedec_DO204();

sub gen_jedec_do() {
    my @arr = (
	# axially leaded diode outlines
	# name, doc, [  body_dia, lead_dia (max), body_length, lead_length, ], mark
	# The following historical DO-types are not done:
	# DO-1 , DO-2 , DO-3 , DO-4 , DO-5 , DO-6 , DO-8 , DO-9 , DO-10, DO-11, DO-12, DO-13, DO-17,
	# DO-18, DO-19, DO-20, DO-21, DO-22, DO-23, DO-24, DO-25, DO-28, DO-30, DO-31, DO-33, DO-36,
	# DO-37, DO-38, DO-40, DO-42, DO-43, DO-44, DO-45, DO-202MA
	[
	 "jedec_DO-7",
	 "# http://www.jedec.org/ DO-7.PDF\n",
	 [ (2.16+2.71)/2, 0.558, (5.85+7.62)/2, 25.4, ],
	],
	[
	 "jedec_DO-14",
	 "# http://www.jedec.org/ DO-14.PDF\n",
	 [ (2.75+3.55)/2, 0.558, (5.85+7.62)/2, 25.4, ],
	],
	[
	 "jedec_DO-15",
	 "# http://www.jedec.org/ DO-15.PDF\n",
	 [ (2.65+3.55)/2, 0.889, (5.85+7.62)/2, 25.4, ],
	],
	[
	 "jedec_DO-16",
	 "# http://www.jedec.org/ DO-16.PDF\n",
	 [ 1.27, 0.33, (1.27+2.54)/2, 11.43, ],
	],
	[
	 "jedec_DO-26",
	 "# http://www.jedec.org/ DO-26.PDF\n",
	 [ (5.5+6.6)/2, 0.99, (8.74+10.41)/2, 35.56, 3 ],
	],
	[
	 "jedec_DO-27",
	 "# http://www.jedec.org/ DO-27.PDF\n",
	 [ (4.83+5.33)/2, 0.914, (7.24+9.52)/2, 28.58, ],
	 [ "bevel", (1.20+2.79)/2 ],
	],
	[
	 "jedec_DO-29",
	 "# http://www.jedec.org/ DO-29.PDF\n",
	 [ (3.05+3.81)/2, 0.838, (8.01+9.14)/2, 25.4, ],
	],
	[
	 "jedec_DO-32",
	 "# http://www.jedec.org/ DO-32.PDF\n",
	 [ (5.97+6.35)/2, 0.813, (8.71+9.53)/2, 25.4, ],
	 [ "bevel", (1.19+1.98)/2 ],
	],
	[
	 "jedec_DO-34",
	 "# http://www.jedec.org/ DO-34.PDF\n",
	 [ (1.27+1.90)/2, 0.558, (2.16+3.04)/2, 12.7, ],
	],
	[
	 "jedec_DO-35",
	 "# http://www.jedec.org/ DO-35.PDF\n",
	 [ (1.53+2.28)/2, 0.558, (3.05+5.08)/2, 12.7, ],
	],
	[
	 "jedec_DO-39",
	 "# http://www.jedec.org/ DO-39.PDF\n",
	 [ (3.31+3.81)/2, 0.914, (3.56+4.06)/2, 28.58, ],
	 [ "bevel", (0.39+1.14)/2 ],
	],
	[
	 "jedec_DO-41",
	 "# http://www.jedec.org/ DO-41.PDF",
	 [ (2.04+2.71)/2, 0.863, (4.07+5.20)/2, 28.0, ],
	],

	# to distinguish bevelled from line marked, I use "b" for bevelled
	[
	 "jedec_DO-201-AAb",
	 "# http://www.jedec.org/ DO-201B.PDF\n# DO-27\n",
	 [ (4.83+5.33)/2, 0.91, (7.24+9.52)/2, 28.58, ],
	 [ "bevel", (1.20+2.79)/2 ],
	],
	[
	 "jedec_DO-201-AA",
	 "# http://www.jedec.org/ DO-201B.PDF\n# DO-27\n",
	 [ (4.83+5.33)/2, 0.91, (7.24+9.52)/2, 28.58, ],
	],
	[
	 "jedec_DO-201-ABb",
	 "# http://www.jedec.org/ DO-201B.PDF\n# DO-32\n",
	 [ (5.97+6.35)/2, 0.81, (8.72+9.52)/2, 25.4, ],
	 [ "bevel", (1.20+1.98)/2 ],
	],
	[
	 "jedec_DO-201-AB",
	 "# http://www.jedec.org/ DO-201B.PDF\n# DO-32\n",
	 [ (5.97+6.35)/2, 0.81, (8.72+9.52)/2, 25.4, ],
	],
	[
	 "jedec_DO-201-ACb",
	 "# http://www.jedec.org/ DO-201B.PDF\n# DO-39\n",
	 [ (3.31+3.81)/2, 0.91, (3.56+4.06)/2, 28.58, ],
	 [ "bevel", (0.39+1.14)/2 ],
	],
	[
	 "jedec_DO-201-AC",
	 "# http://www.jedec.org/ DO-201B.PDF\n# DO-39\n",
	 [ (3.31+3.81)/2, 0.91, (3.56+4.06)/2, 28.58, ],
	],
	[
	 "jedec_DO-201-ADb",
	 "# http://www.jedec.org/ DO-201B.PDF\n# ref 2-23\n",
	 [ (4.78+6.35)/2, 1.42, (7.24+9.52)/2, 25.4, ],
	 [ "bevel", (1.20+2.79)/2 ],
	],
	[
	 "jedec_DO-201-AD",
	 "# http://www.jedec.org/ DO-201B.PDF\n# ref 2-23\n",
	 [ (4.78+6.35)/2, 1.42, (7.24+9.52)/2, 25.4, ],
	],
	[
	 "jedec_DO-201-AE",
	 "# http://www.jedec.org/ DO-201B.PDF\n# ref 10-453\n",
	 [ (2.04+2.71)/2, 0.863, (4.07+5.20)/2, 28.0, ],
	],

	);
    gen_axial_diodes(@arr);
}
#gen_jedec_do();

##############################
# radial types

sub gen_radial($$$ ; $$) { # two pin symmetrical
    my $name = shift;
    my $doc  = shift;
    my $dim  = shift;

    my $mark  = shift;
    my $pin_name = shift;

    my ($xw, $yw, $zh, $cr, $lead_dia, $sep, $lead_length) = @$dim;
    if (!defined($mark)) { $mark = []; }
    if (!defined($pin_name)) { $pin_name = [ "", "" ]; }
    if (!defined($lead_length)) { $lead_length = 0; }

    my $drill = lead_to_drill($lead_dia);
    my @thickness = drill2thickness($drill);

    #print "gen_radial(): $xw, $zh, $cr, $lead_dia/$drill, $sep, $lead_length\n";
    my @mounting = ( "" );
    if ($lead_length) { push @mounting, ("U", "D" ); }
    for my $mnt (@mounting) {
	for (my $ix = 0; $ix < @thickness; $ix++) {
	    my $file = sprintf("%s%s%s.fp", $name, $mnt, thickness_suffix($ix));
	    my $limit_radius = $thickness[$ix]/2 + $mask_gap;
	    #print "<$mnt> $thickness[$ix], $mask_gap, $file, $limit_radius\n";
	    if ($sep < $thickness[$ix] + $mask_gap) {
		#warn "$file: too close spacing <$spacing $limit_radius";
		next;
	    }

	    element_start($file, $doc);
	    #$round_first_pin = 1;
	    pin( -$sep/2, 0, $drill, $thickness[$ix], $$pin_name[0] );
	    pin(  $sep/2, 0, $drill, $thickness[$ix], $$pin_name[1] );
	    pr("  # body\n");

	    my @bbw = bb_enlarge($silk_w/2, @bounding_box);
	    if ($mnt eq "") {
		silk_crect($origin, [$xw, $yw], $cr, \@bbw);
		if (@$mark) {
		    # mark is always on pin 1 here (my convention)
		    my @arr = @$mark;
		    my $type = $$mark[0];
		    if ($type eq "line") {
			my $brd = [ 0.25 * $xw/2, ];
			silk_fillleft(-$xw/2, -$yw/2, $yw/2, $cr, $brd);
		    } elsif ($type eq "+") {
			my $l = 2;
			silk_cross($xw/2 + 1 + $l/2, 0, 2);
		    } else {
		    }
		}
	    } elsif ($mnt eq "U") {
		silk_blrect([-$xw/2, -$lead_length], [$xw,-$yw], 1, \@bbw);
	    } elsif ($mnt eq "D") {
		silk_blrect([-$xw/2,  $lead_length], [$xw, $yw], 1, \@bbw);
	    }

	    element_stop();
	}
    }
}
sub gen_radial_pol($$$) {
    my $name = shift;
    my $doc  = shift;
    my $dim  = shift;

    my $mark     = [ "line"             ];
    my $pin_name = [ "Cathode", "Anode" ];
    gen_radial($name, $doc, $dim, $mark, $pin_name);
}
sub gen_radial_list(@) {
    for my $r (@_) {
	my ($name, $doc, $dim, $mark, $pin_name) = @$r;
	gen_radial($name, $doc, $dim, $mark, $pin_name);
    }
}
sub gen_radial_list_pol(@) {
    for my $r (@_) {
	my ($name, $doc, $dim, $mark, $pin_name ) = @$r;
	if (!defined($mark    )) { $mark     = [ "line"             ]; }
	if (!defined($pin_name)) { $pin_name = [ "Cathode", "Anode" ]; }
	gen_radial($name, $doc, $dim, $mark, $pin_name);
    }
}

sub gen_round_led($) { # th
    my $r = shift;
    my ($name, $doc, $type, $or, $ir, $zh, $fh, $zr, $sep, $lead_length, $lt, $lw, $sw) = @$r;
    # $type: flat, round or rect
    # $or: bottom flange outer radi
    # $ir: plastic body radi
    # $zh: total height of plastic body
    # $fh: flange height
    # $zr: radi of top, 0 => flat top
    # $sep: lead separation
    # $lead_length: length of shortest lead
    # $lt: lead width, normal to the separation line
    # $lw: lead width, along the separation line
    # $sw: lead width, at widest point
    if (!defined($sw)) { $sw = $lw; }
    my $pin_name = [ "Cathode", "Anode" ];
    my $lead_dia = triangle_r($lt, $lw);
    my $lead2    = triangle_r($lt, $sw);
    my $drill  = lead_to_drill($lead_dia);
    my $drill2 = lead_to_drill($lead2);
    my @thickness = drill2thickness($drill);
    my $file;

    my @mounting = ();
    if ($drill < $drill2) { @mounting = ("s"); }
    # u = up, d down, r right, l left, s above standoffs, n normal close to pcb
    push @mounting, qw/ u d r l n /;
    for my $mnt (@mounting) {
	if ($drill < $drill2 && $mnt eq "n") { # bigger hole due to standoff
	    $drill = $drill2;
	    @thickness = drill2thickness($drill2);
	}
	for (my $ix = 0; $ix < @thickness; $ix++) {
	    my $limit_radius = $thickness[$ix]/2 + $mask_gap;
	    if ($sep < $thickness[$ix] + $mask_gap) { next; }

	    my $rh = $zr;
	    my $angle = 90;
	    if ($zr > $ir) {
		$rh = circle_segment_h($zr, 2*$ir);
		$angle = rad_deg(asin($ir/$zr));
	    }

	    my @bend;
	    my $bend_step = 5;
	    my $bend_max = rounddown($lead_length - ($or+1.6+2), $bend_step);
	    for (my $bend = 0; $bend <= $bend_max; $bend += $bend_step) { push @bend, $bend; }
	    for my $bend (@bend) {
		my $file;
		if ($mnt eq "n" || $mnt eq "s") {
		    if ($bend == 0) {
			$file = sprintf("%s_%s%s.fp", $name, $mnt, thickness_suffix($ix));
		    } else {
			next;
		    }
		} else {
		    if ($bend == 0) {
			next;
		    } else {
			$file = sprintf("%s_%s%02d%s.fp", $name, $mnt, $bend, thickness_suffix($ix));
		    }
		}
		element_start($file, $doc);
		pin( -$sep/2, 0, $drill, $thickness[$ix], $$pin_name[0] );
		pin(  $sep/2, 0, $drill, $thickness[$ix], $$pin_name[1] );
		# polarity marks, def. pos.
		my $polx = $sep/2+$thickness[$ix]/2 + $silk_w;
		my $poly = -$thickness[$ix]/2 - $mask_gap - $silk_w;
		my $poll = $drill*0.75;

		pr("# body\n");
		my $silk_thin = 0.12;
		my @bbw  = bb_enlarge($silk_w/2, @bounding_box);
		my @bbth = bb_enlarge($silk_thin/2, @bounding_box);
		my ($lr, $bl, $rhl,  $fhl, $zhl, $zrl, $sta);
		if ($bend == 0 && ($mnt eq "n" || $mnt eq "s")) {
		    # normally straight/standing led
		    if    ($type eq "flat" ) {
			silk_width($silk_thin);
			silk_circle($origin, $ir, 0, 360, \@bbth);
			silk_width();
			silk_circle_flat($origin, $or, $ir, 0, \@bbw);
		    } elsif ($type eq "round") {
			silk_width($silk_thin);
			silk_circle($origin, $ir, 0, 360, \@bbth);
			silk_width();
			silk_circle($origin, $or, 0, 360, \@bbw);
		    } elsif ($type eq "rect" ) {
			silk_crect($origin, [$or, $ir], 0, \@bbw);
			$poly = -$ir/2 - $poll;
		    }
		    if ($type ne "rect" && ( $polx < $or + $poll ) ) {
			$polx =  0.7 * ($or + $poll);
			$poly = -$polx;
		    }
		} elsif ($bend != 0 && $mnt =~ /[ud]/) { # bent down/up
		    if ($mnt eq "d") {
			($lr, $bl, $rhl,  $fhl, $zhl, $zrl, $sta) = ( $limit_radius,  $bend,  $rh,  $fh,  $zh,  $zr,  90);
		    } else {
			($lr, $bl, $rhl,  $fhl, $zhl, $zrl, $sta) = (-$limit_radius, -$bend, -$rh, -$fh, -$zh, -$zr, -90);
		    }

		    # component leads
		    silk_start(-$sep/2, $bl);
		    silk_line (-$sep/2,   0, \@bbw);
		    silk_start( $sep/2, $bl);
		    silk_line ( $sep/2,   0, \@bbw);

		    # body sides and bottom
		    if ($type eq "flat") {
			silk_start(-$ir, $bl + $zhl - $rhl);
			silk_line (-$ir, $bl);
			silk_line ( $or, $bl);
			silk_line ( $or, $bl + $fhl);
			silk_line (-$ir, $bl + $fhl);
			silk_start( $ir, $bl + $fhl);
			silk_line ( $ir, $bl + $zhl - $rhl);
		    } elsif ($type eq "round") {
			if ($mnt eq "d") { silk_rect([-$or,$bl     ], [$or,$bl+$fhl], 0); }
			else             { silk_rect([-$or,$bl+$fhl], [$or,$bl     ], 0); }
			silk_start( -$ir, $bl + $zhl - $rhl);
			silk_line ( -$ir, $bl + $fhl       );
			silk_start(  $ir, $bl + $fhl       );
			silk_line (  $ir, $bl + $zhl - $rhl);
		    } elsif ($type eq "rect") {
			# $or = $xw, $ir = $yw
		        if ($mnt eq "d") { silk_rect([-$or/2,$bl     ], [$or/2,$bl+$zhl], 0); }
			else             { silk_rect([-$or/2,$bl+$zhl], [$or/2,$bl     ], 0); }
		    }

		    # body top
		    if ($zr > 0) {
			silk_arc([0, $bl + $zhl - $zrl], $zr, $sta - $angle, 2*$angle);
			if ($zr < $ir) {
			    silk_width(0.12);
			    silk_start(-$ir + 0.5, $bl + $zhl - $rhl);
			    silk_rline(2*$ir - 1, 0);
			    silk_width();
			} elsif ($zr > $ir) {
			    silk_start(-$ir, $bl + $zhl - $rhl);
			    silk_rline(2*$ir, 0);
			}
		    }

		} elsif ($bend != 0 && $mnt =~ /[rl]/) { # bent right/left
		    my $other_end;
		    if ($mnt eq "r") { # bent right
			($lr, $bl, $rhl,  $fhl, $zhl, $zrl, $sta) =
			    ( $sep/2+$limit_radius,  $bend,  $rh,  $fh,  $zh,  $zr, 180);
			$other_end = -$sep/2;
		    } else { # bent left
			($lr, $bl, $rhl,  $fhl, $zhl, $zrl, $sta) =
			    (-$sep/2-$limit_radius, -$bend, -$rh, -$fh, -$zh, -$zr,   0);
			$other_end = $sep/2;
		    }
		    # component leads
		    silk_start( $bl,  0);
		    silk_line ( $other_end, 0, \@bbw);

		    if ($type eq "flat" || $type eq "round") {
			if ($mnt eq "r") { silk_rect([$bl     ,-$or], [$bl+$fhl,$or], 0); }
			else             { silk_rect([$bl+$fhl,-$or], [$bl     ,$or], 0); }

			silk_start( $bl + $zhl - $rhl, -$ir);
			silk_line ( $bl + $fhl       , -$ir);
			silk_start( $bl + $fhl       ,  $ir);
			silk_line ( $bl + $zhl - $rhl,  $ir);
			if ($mnt eq "r" && $type eq "flat") {
			    my $y = triangle_x($or, $ir);
			    silk_start( $bl       , -$y);
			    silk_line ( $bl + $fhl, -$y);
			    silk_start( $bl       ,  $y);
			    silk_line ( $bl + $fhl,  $y);
			}

			if ($zr > 0) {
			    silk_arc([$bl + $zhl - $zrl, 0], $zr, $sta - $angle, 2*$angle);
			    if ($zr < $ir) {
				silk_width(0.12);
				silk_start( $bl + $zhl - $rhl, -$ir + 0.5);
				silk_rline(0, 2*$ir - 1);
				silk_width();
			    } elsif ($zr > $ir) {
				silk_start( $bl + $zhl - $rhl, -$ir);
				silk_rline(0, 2*$ir);
			    }
			}
		    } elsif ($type eq "rect") {
			# $or = $xw, $ir = $yw
			if ($mnt eq "r") { silk_rect([$bl     ,-$ir/2], [$bl+$zhl, $ir/2], 0); }
			else             { silk_rect([$bl+$zhl,-$ir/2], [$bl     , $ir/2], 0); }
		    }


		} else {
		}
		pr("# polarity marks\n");
		silk_cross( $polx, $poly, $poll);
		silk_start(- $polx - $poll/2, $poly);
		silk_rline($poll, 0);

		element_stop();
#		print "file: $file\n"; # TEST
#		last; # TEST
	    }
#	    last; # TEST
	}
#	    last; # TEST
    }
}
sub gen_round_led_list(@) {
    for my $r (@_) { gen_round_led($r); }
}

sub gen_round_leds() {
    my @arr = (
	# $name, $doc,
	# "rect", $xw, $yw, $zh, $fh, $zr, $sep, $lead_length, $lt, $lw, $sw
	# $type , $or, $ir, $zh, $fh, $zr, $sep, $lead_length, $lt, $lw, $sw
	[ "kingbright_L9294",
	  "# Wide-view led (130°)\n# http://www.farnell.com/datasheets/1519863.pdf\n",
	  "flat", 5.8/2, 4.8/2, 4.85, 1.5, 2.95 , 2.54, 27-1.5, 0.5, 0.5, 0.7,
      ],
	[ "kingbright_T-1_3mm",
	  "# http://www.farnell.com/datasheets/67148.pdf\n",
	  "round", 2.9/2, 2.8/2, 4.60, 1.0, 2.8/2, 2.54, 27-1.5, 0.5, 0.5, 0.7,
      ],
	[ "kingbright_T-1_5mm",
	  "# http://www.farnell.com/datasheets/67139.pdf\n# http://www.lumex.com/specs/SSL-LX5093HD.pdf\n",
	  "flat", 5.9/2, 5.0/2, 8.60, 1.0, 5.0/2, 2.54, 25-1.5, 0.5, 0.5, 0.7,
      ],
	[ "bulgin_A1050",
	  "# p362 http://www.bulgin.com/media/import/Bulgin_Catalogue_High_Quality.pdf\n",
	  "flat", 5.9/2, 5.0/2, 8.60, 1.0, 5.0/2, 2.54, 25-1.5, 0.5, 0.5, 0.7,
      ],
	[ "everlight_24x49",
	  "# http://www.everlight.com/upload/product_pdf/1533UYD_S530_A3.pdf\n",
	  "rect", 4.9, 2.4, 9.70, 0, 0, 2.54, 25.4, 0.5, 0.5,
      ],
	[ "würth_151031xS06000",
	  "# https://www.we-online.com/components/products/datasheet/151031YS06000.pdf\n",
	  "flat", 3.95/2, 3.0/2, 5.3, 1.0, 3.0/2, 2.54, 25.4, 0.5, 0.5, 0.75,
      ],

    );
    gen_round_led_list(@arr);
}
#gen_round_leds();

sub gen_cree_led() {
    my $name = "cree_xlamp_ML-E";
    my $doc  = "# https://assets.cree-led.com/a/ds/x/XLamp-MLE.pdf\n";
    my $desc = "";
    my $refdes = "D?";
    my $value = undef;

    my $file = $name . ".fp";

    my $body = [ 3.15, 3.50 ];
    my $cx = (4.25+1.65)/4;
    my $cy = (3.20+0.70)/4;
    my $px = (4.25-1.65)/2;
    my $py = (3.20-0.70)/2;
    element_start($file, $doc, $desc, $refdes, $value);

    pad(0,0, 0.70, 3.20,  "die heatsink", "", 0, 0);

    pad( $cx, -$cy,  $px, $py,  "Cathode", "", 0, 1);
    pad( $cx,  $cy,  $px, $py,  "Cathode", "", 0, 1);

    pad(-$cx, -$cy,  $px, $py,  "Anode"  , "", 0, 2);
    pad(-$cx,  $cy,  $px, $py,  "Anode"  , "", 0, 2);

    my @bbw = bb_enlarge($silk_w/2, @bounding_box);
    silk_crect($origin, $body, 0, \@bbw);
    bb_right_side(@bbw[1..2]);
    element_stop();
}
#gen_cree_led();

sub gen_panasonic_ellyt() {
    my $sz_str;
    my $case_str;
    my @case;
    my @dim;

    $sz_str = "
dia   4    5    5   6.3  6.3 8   10    12.5 12.5  16   18
len    .   ==7 >=11 ==7  >7   .    .   <=25 >25     .    .
lead  0.45 0.45 0.5 0.45 0.5 0.6  0.6   0.6  0.8   0.8  0.8
sep   1.5  2.0  2.0 2.5  2.5 3.5  5.0   5.0  5.0   7.5  7.8
";

    # body diameter / body length (height)
    $case_str = "
 4    7
 5    7
 6.3  7
 4   11
 5   11
 5   15
 6.3 11.2
 6.3 15
 8   11.5
 8   15
 8   20
10   12.5
10   16
10   20
10   25
10   30
12.5 15
12.5 20
12.5 25
12.5 30
12.5 35
12.5 40
16   15
16   20
16   25
16   31.5
16   35.5
16   40
18   15
18   20
18   25
18   31.5
18   35.5
18   40
";

    for my $str (split(/\n/, $case_str)) {
	$str = str_trim($str);
	next if ($str eq "");
	my @fld = split(/ /, $str);
	push @case, [ @fld ];
	#print join("x", @fld), "\n";

    }

    my %sz;
    {
	my @arr;
	my @aa;
	for (split(/\n/, $sz_str)) {
	    next if (m/^$/);
	    push @arr, [ split() ];
	}
	for (my $ix = 0; $ix < @arr; $ix++) {
	    my $r = $arr[$ix];
	    for (my $kx = 0; $kx < @$r; $kx++) {
		$aa[$kx][$ix] = $arr[$ix][$kx];
	    }
	}
	for (my $ix = 1; $ix < @aa; $ix++) {
	    my @vec = @{$aa[$ix]};
	    my $d = shift @vec;
	    if (!defined($sz{$d})) {
		$sz{$d} = [];
	    }
	    push @{$sz{$d}}, [ @vec ];
	}
    }

    #print Dumper(%sz);
    for my $r (@case) {
	my $d = $$r[0];
	my $l = $$r[1];

	#print "$d $l\n";
	my $szr = $sz{$d};
	if (!defined($szr)) {
	    warn("\$sz{\$d} undefined");
	}
	my $lead;
	my $sep;
	if (@{$szr} == 1) {
	    my $r = $$szr[0];
	    my $len  = $$r[0];
	    $lead = $$r[1];
	    $sep  = $$r[2];
	    #print "sing ${d}x$l $lead $sep\n";
	} else {
	    for my $r (@{$szr}) {
		my $len  = $$r[0];
		if      ($len =~ m/^==([0-9.]+)$/ && $l == $1) {
		    $lead = $$r[1]; $sep  = $$r[2];
		} elsif ($len =~ m/^<([0-9.]+)$/  && $l <  $1) {
		    $lead = $$r[1]; $sep  = $$r[2];
		} elsif ($len =~ m/^<=([0-9.]+)$/ && $l <= $1) {
		    $lead = $$r[1]; $sep  = $$r[2];
		} elsif ($len =~ m/^>=([0-9.]+)$/ && $l >= $1) {
		    $lead = $$r[1]; $sep  = $$r[2];
		} elsif ($len =~ m/^>([0-9.]+)$/  && $l >  $1) {
		    $lead = $$r[1]; $sep  = $$r[2];
		} else {
		    #print "$d $l: not this one, |$len|$$r[1]|$$r[2]|\n";
		}
	    }
	    if (!defined($lead) || !defined($sep)) {
		warn("$d $l // lead or sep !defined");
		next;
	    }
	    #print "mult ${d}x$l $lead $sep\n";
	}
	#print "Todo ${d}x$l $lead $sep\n";

	my $name = sprintf "panasonic_ellyt_%03dx%03d", $d*10, $l*10;
	my $doc =
"# Panasonic Aluminum Electrolytic Capacitors
# http://eu.industrial.panasonic.com/sites/default/pidseu/files/downloads/files/id_almiec_e.pdf
";
	my $dim = [ $d, $d, $l, $d/2, $lead, $sep, 0];
	gen_radial_pol($name, $doc, $dim);
    }
}
#gen_panasonic_ellyt();

sub gen_txc_hc49s() {
    my $name = "txc_hc49s";
    my $doc = "# http://www.txccrystal.com/images/pdf/9b.pdf\n";
    my $xd = 11.5;
    my $yd =  5.0;
    my $zd =  3.68;
    #id 3.8;
    my $lead = 0.43+0.125;
    my $sep = 4.88;
    #my $lead_len = 13.2;
    my $dim = [ $xd, $yd, $xd, $yd/2, $lead, $sep ];
    $round_first_pin = 1;
    gen_radial($name, $doc, $dim);
    $round_first_pin = 0;
}
#gen_txc_hc49s();

sub gen_bi_hm15() {
    my $drill = 0.9;
    my $cu_dia = int(10 * $drill * 1.7 + 0.5) / 10;
    my $doc =
"# http://www.ttelectronicsmagnetics.com/pdf/datasheets/hm15.pdf
# https://www1.elfa.se/data1/wwwroot/assets/datasheets/HM15-10150LF_eng_tds.pdf
";

    my @thickness = drill2thickness($drill);
    $round_first_pin = 1;
    for (my $ix = 0; $ix < @thickness; $ix++) {
	my $name = "bi_hm15_1";
	my $file = sprintf("%s%s.fp", $name, thickness_suffix($ix));
	element_start($file, $doc);
	pin( -15.24/2, -10.16/2, $drill, $thickness[$ix]);
	pin(  15.24/2,  10.16/2, $drill, $thickness[$ix]);
	pr("\n");
	silk_crect([0,0], [17.78, 12.7], 0);
	element_stop();

	$name = "bi_hm15_2";
	$file = sprintf("%s%s.fp", $name, thickness_suffix($ix));
	element_start($file, $doc);
	pin( -10.16/2,  15.24/2, $drill, $thickness[$ix]);
	pin(  10.16/2, -15.24/2, $drill, $thickness[$ix]);
	pr("\n");
	silk_crect([0,0], [17.78, 17.78], 0);
	element_stop();
    }
    $round_first_pin = 0;
}
#gen_bi_hm15();

sub gen_tdk_B82730() {
    my $lead = 0.6;
    my $drill = lead_to_drill($lead);
    my $name = "tdk_B82730";
    my $doc = "# https://www.farnell.com/datasheets/3158422.pdf\n";
    my ($cx, $cy) = (8/2, 7/2);
    my %version = ( U => 11, G => 15);
    my $bx = 16.5;
    my $by = 11;

    my @thickness = drill2thickness($drill);
    $round_first_pin = 1;
    for (my $ix = 0; $ix < @thickness; $ix++) {
	for my $k (keys %version) {
	    my $v = $version{$k};

	    my $file = sprintf("%s%s%s.fp", $name, $k, thickness_suffix($ix));
	    element_start($file, $doc);
	    pin( -$cx,  $cy, $drill, $thickness[$ix]);
	    pin(  $cx,  $cy, $drill, $thickness[$ix]);
	    pin(  $cx, -$cy, $drill, $thickness[$ix]);
	    pin( -$cx, -$cy, $drill, $thickness[$ix]);

	    my @bbw = bb_enlarge($silk_w/2, @bounding_box);
	    # TODO: correct bb.
	    silk_crect([0, ($v-$by)/2], [$bx, $v], 0, \@bbw);
	    element_stop();
	}
    }
    $round_first_pin = 0;
}
#gen_tdk_B82730();

sub gen_buzzer() {
    my $mark     = [ "+"                ];
    my $pin_name = [ "Cathode", "Anode" ];

    # name doc dim mark pin_name
    # dim = [ $xw, $yw, $zh, $cr, $lead_dia, $sep, $lead_length ]
    my @data = (
	[ "beeper_9.6",
	  "# https://dbunlimitedco.com/images/product_images/2D-Drawings/IE092505-1.pdf\n",
	  [ 9.6, 9.6, 7.5, 9.6/2, 0.6, 5, 0 ],
	  $mark, $pin_name,
	], [ "digisound_f_ucw06",
	     "# Beeper dia 12, cc 7.6\n" .
	     "# http://www1.elfa.se/data1/wwwroot/assets/datasheets/iy560651_d_e.pdf\n" .
	     "# http://www.farnell.com/datasheets/1653447.pdf is similar\n",
	     [ 12, 12, 7.5, 12/2, 0.65, 7.6, 0 ],
	     $mark, $pin_name,
	], [ "samesky_CPI-137-12T",
	     "# https://eu.mouser.com/datasheet/2/670/cpi_137_12t-1777487.pdf\n",
	     [ 13.9, 13.9, 7.5, 13.9/2, 0.7, 7.6, 0 ],
	     $mark, $pin_name,
	],
    );

    gen_radial_list(@data);
}
#gen_buzzer();

sub gen_murata_1400() {
    my $name = "murata";
    my $doc = "# http://www.farnell.com/datasheets/1697186.pdf";

    my @line = split("\n",
# order code  uH   A      Ohm  Q at f   SRF   a    b    c   d    e    f   g
"1410313C     10  13    0.009  54  50  20.7  27.0 24.4 14.0 1.30 5.5 23.9 2.6
1415312C      15  12    0.009  42  50  12.7  27.0 24.4 14.0 1.30 5.5 23.9 2.6
1422311C      22  11    0.014  64 100   9.3  27.0 24.4 14.0 1.30 5.5 23.9 2.6
1433393C      33   9.3  0.017  27  50   9.1  27.0 24.4 14.0 1.30 5.5 23.9 2.6
1447383C      47   8.3  0.019  40 100   6.0  27.0 24.4 18.5 1.30 5.5 23.9 2.6
1447385C      47   8.5  0.021  33 100   6.7  26.8 24.4 14.0 1.20 5.5 23.8 2.4
1468362C      68   6.2  0.032  32 100   5.3  26.5 24.4 14.0 1.08 5.5 23.7 2.1
1468373C      68   7.3  0.025  45 100   5.3  27.0 24.4 18.5 1.30 5.5 23.9 2.6
1410454C     100   5.4  0.046  24 100   4.6  26.4 24.4 14.0 1.02 5.5 23.6 2.0
1410460C     100   6.0  0.033  37 100   3.9  26.8 24.4 18.5 1.20 5.5 23.8 2.4
1410478C     100   7.8  0.040  34  50   3.3  32.4 29.8 21.8 1.30 5.1 29.3 2.6
1415440C     150   4.0  0.069  24  50   3.4  26.2 24.4 14.0 0.90 5.5 23.5 1.8
1415449C     150   4.9  0.055  34  50   2.9  26.4 24.4 18.5 1.02 5.5 23.6 2.0
1415465C     150   6.5  0.042  46 100   2.4  32.2 29.8 21.8 1.20 5.1 29.2 2.4
1422435C     220   3.5  0.096  22  50   2.8  26.1 24.4 14.0 0.85 5.5 23.5 1.7
1422441C     220   4.1  0.073  33 100   2.3  26.3 24.4 18.5 0.97 5.5 23.6 1.9
1422455C     220   5.5  0.062  30  50   2.2  32.1 29.8 21.8 1.14 5.1 29.1 2.2
1430430C     300   3.0  0.140  26  50   2.6  25.9 24.4 14.0 0.75 5.5 23.4 1.5
1430433C     300   3.3  0.100  37  50   2.2  26.2 24.4 18.5 0.90 5.5 23.5 1.8
1430450C     300   5.0  0.080  28  50   1.7  31.8 29.8 21.8 1.02 5.1 29.0 2.0
1433428C     330   2.8  0.150  22  50   2.5  25.9 24.4 14.0 0.76 5.5 23.4 1.5
1433433C     330   3.3  0.120  29  50   2.0  26.2 24.4 18.5 0.90 5.5 23.5 1.8
1433445C     330   4.5  0.091  25  50   1.6  31.8 29.8 21.8 1.02 5.1 29.0 2.0
1447423C     470   2.3  0.250  34  50   2.0  25.7 24.4 14.0 0.67 5.5 23.3 1.3
1447427C     470   2.7  0.160  25  50   1.6  26.1 24.4 18.5 0.85 5.5 23.5 1.7
1447440C     470   4.0  0.125  24  50   1.4  31.7 29.8 21.8 0.97 5.1 29.0 1.9
1468420C     680   2.0  0.300  23  50   1.6  25.7 24.4 14.0 0.67 5.5 23.3 1.3
1468422C     680   2.2  0.226  28  50   1.3  25.9 24.4 18.5 0.75 5.5 23.4 1.5
1468431C     680   3.1  0.173  60  10   1.0  31.6 29.8 21.8 0.90 5.1 28.9 1.8
1410516C   1.0mH   1.6  0.460  30  50   1.4  25.6 24.4 14.0 0.60 5.5 23.2 1.2
1410517C   1.0mH   1.7  0.336  35  50   1.2  25.7 24.4 18.5 0.67 5.5 23.3 1.3
1410524C   1.0mH   2.4  0.277  33  50   1.0  31.4 29.8 21.8 0.79 5.1 28.8 1.5
1415513C   1.5mH   1.3  0.680  34  50   1.0  25.5 24.4 14.0 0.54 5.5 23.1 1.0
1415514C   1.5mH   1.4  0.550  47  50   0.8  25.6 24.4 18.5 0.60 5.5 23.2 1.2
1415517C   1.5mH   1.7  0.374  28  50   0.7  31.3 29.8 21.8 0.75 5.1 28.8 1.5
1422509C   2.2mH   0.9  1.000  43  50   0.9  25.3 24.4 14.0 0.48 5.5 23.1 0.9
1422512C   2.2mH   1.2  0.700  33  50   0.7  25.6 24.4 18.5 0.60 5.5 23.2 1.2
1422514C   2.2mH   1.4  0.622  33  50   0.6  31.1 29.8 21.8 0.67 5.1 28.7 1.3
1433507C   3.3mH   0.7  1.428  45  50   0.8  25.2 24.4 14.0 0.43 5.5 23.0 0.8
1433510C   3.3mH   1.0  1.992  20  50   0.7  25.5 24.4 18.5 0.54 5.5 23.1 1.0
1433512C   3.3mH   1.2  0.930  20  50   0.5  31.0 29.8 21.8 0.60 5.1 28.6 1.2
1447506C   4.7mH   0.6  2.200  60  50   0.6  25.2 24.4 14.0 0.39 5.5 23.0 0.7
1447508C   4.7mH   0.8  1.600  65  50   0.5  25.3 24.4 18.5 0.48 5.5 23.1 0.9
1447509C   4.7mH   0.9  1.400  57  10   0.5  30.9 29.8 21.8 0.54 5.1 28.5 1.0
1468505C   6.8mH   0.5  2.880  50  50   0.5  25.2 24.4 14.0 0.39 5.5 23.0 0.7
1468507C   6.8mH   0.7  2.300  47  50   0.4  25.2 24.4 18.5 0.43 5.5 23.0 0.8
1468508C   6.8mH   0.8  2.100  30  50   0.4  30.7 29.8 21.8 0.48 5.1 28.5 0.9
1410604C   10mH    0.4  4.340  51  50   0.4  25.1 24.4 14.0 0.34 5.5 22.9 0.6
1410605C   10mH    0.5  3.600  48  50   0.3  25.2 24.4 18.5 0.39 5.5 23.0 0.7
1410606C   10mH    0.6  2.600  48  50   0.2  30.9 29.8 21.8 0.54 5.1 28.5 1.0
1415604C   15mH    0.4  5.500  61  10   0.2  25.1 24.4 18.5 0.34 5.5 22.9 0.6
1415605C   15mH    0.5  3.740  55  10   0.2  30.6 29.8 21.8 0.43 5.1 28.4 0.8
1422604C   22mH    0.4  6.962  30  50   0.2  30.5 29.8 21.8 0.34 5.1 28.3 0.6
");

    for my $str (@line) {
	my ($code, $ind, $amp, $ohm, $Q, $frq, $srf, $a, $b, $c, $d, $e, $f, $g) =
	    split (/[ \t]+/, $str);
	#print $str, "\n";
	#print "$code $ind $amp $ohm $Q $frq $srf $a $b $c $d $e $f $g\n";

	my $name2 = "${name}_${code}_";
	my  ($xw, $yw, $zh,  $cr, $lead_dia, $sep, $lead_length) =
	    ( $b,  $b,  $c, $b/2,        $g,   $f,            0);

	my $dim = [ $xw, $yw, $zh,  $cr, $lead_dia, $sep, $lead_length ];
	gen_radial($name2, $doc, $dim);
    }
}
#gen_murata_1400();

sub gen_coilcraft_th_power() {
    my $name  = "coilcraft";
    my $doc   = "# https://www.coilcraft.com/getmedia/beede189-faf8-4b6b-825f-8ce276b0c18c/ShortFormCatalog_EU.pdf p.42-44\n";

    my @data = split("\n",
#Series	  A max	  B max	  C	  D	  E
# dimensions in inch and mm
"
RFC0807	0.35 8,80	0.30 7,50	0.024 0,60	0.197 5,0	0.197 5,0
RFS1113	0.43 11,0	0.48 12,3	0.031 0,80	0.189 4,8	0.197 5,0
RFS1317	0.52 13,3	0.63 16,0	0.031 0,80	0.189 4,8	0.197 5,0
RFS1412	0.54 13,7	0.46 11,7	0.031 0,80	0.189 4,8	0.295 7,5

DR0608	0.30 7,50	0.39 10,0	0.024 0,60	0.157 4,0	0.138 3,5
DR0810	0.41 10,5	0.47 12,0	0.024 0,60	0.157 4,0	0.197 5,0
RFC0810	0.37 9,50	0.45 11,5	0.024 0,60	0.197 5,0	0.197 5,0
RFC1010	0.43 11,0	0.45 11,5	0.031 0,80	0.197 5,0	0.236 6,0

RFB0807	0.35 8,80	0.30 7,50	0.024 0,60	0.157 4,0	0.197 5,0
RFB0810	0.37 9,50	0.45 11,5	0.024 0,60	0.157 4,0	0.197 5,0
RFB1010	0.43 11,0	0.45 11,5	0.031 0,80	0.157 4,0	0.236 6,0
"
);

    for my $str (@data) {
	next unless $str;
	$str =~ tr/,/./;
	my ($series, $a, $A, $b, $B, $c, $C, $d, $D, $e, $E) = split(/[ \t]+/, $str);
	#print $str, "\n";
	#print join(" ", $series, $a, $A, $b, $B, $c, $C, $d, $D, $e, $E), "\n";

	my $name2 = "${name}_${series}_";
	my  ($xw, $yw, $zh,  $cr, $lead_dia, $sep, $lead_length) =
	    ( $A,  $A,  $B, $A/2,        $C,   $E,            0);

	my $dim = [ $xw, $yw, $zh,  $cr, $lead_dia, $sep, $lead_length ];
	gen_radial($name2, $doc, $dim);
    }
}
#gen_coilcraft_th_power();

sub gen_pin_matrix($$$ $$$ ; $$&$) {
    my $name  = shift;
    my $doc   = shift;
    my $order = shift; # "x" first, "y" first or "d" dil numbering, top left pin is pin 1

    my $sep   = shift; # [ $x_sep, $y_sep ]
    my $num   = shift; # [ $x_count, $y_count ]
    my $drill = shift; # drill diameter

    my $orig  = shift; # position of element origin, [0,0] => pin 1, undef => mid of all pins
    my $pin_name = shift; # actual_pin_name = $$pin_name[$pin_number];
    my $func = shift;
    my $data = shift;

    if ($$num[0] < 1 || $$num[1] < 1) { return; }

    if (!defined($orig)) {
	$orig = [ $$sep[0] * ($$num[0]-1)/2, $$sep[1] * ($$num[1]-1)/2 ];
    }
    my $pnf = !defined($pin_name);

    my $min_sep = $$sep[0];
    if    ($$num[0] < 2) { $min_sep = $$sep[1]; }
    elsif ($$num[1] < 2) { }
    elsif ($min_sep > $$sep[1]) { $min_sep = $$sep[1]; }

    my @thickness = drill2thickness($drill);
    if ($min_sep > $mask_gap) { push @thickness, $min_sep - $mask_gap; }

    for (my $it = 0; $it < @thickness; $it++) {
	my $file = sprintf("%s%s.fp", $name, thickness_suffix($it));
	my $limit_radius = $thickness[$it]/2 + $mask_gap;
	if ($min_sep < $thickness[$it] + $mask_gap) { next; }
	my $pin_num = 0;

	element_start($file, $doc);
	if ($order eq "x") {
	    for (my $ix = 0; $ix < $$num[0]; $ix++) {
		for (my $iy = 0; $iy < $$num[1]; $iy++) {
		    $pin_num++;
		    my $pn = $$pin_name[$pin_num];
		    if ($pnf || defined($pn) && $pn ne "") {
			pin( $ix*$$sep[0]-$$orig[0], $iy*$$sep[1]-$$orig[1], $drill, $thickness[$it], $pn, "", $pin_num );
		    }
		}
	    }
	} elsif ($order eq "y") {
	    for (my $iy = 0; $iy < $$num[1]; $iy++) {
		for (my $ix = 0; $ix < $$num[0]; $ix++) {
		    $pin_num++;
		    my $pn = $$pin_name[$pin_num];
		    if ($pnf || defined($pn) && $pn ne "" ) {
			pin( $ix*$$sep[0]-$$orig[0], $iy*$$sep[1]-$$orig[1], $drill, $thickness[$it], $pn, "", $pin_num );
		    }
		}
	    }
	} elsif ($order eq "d") {
	    for (my $ix = 0; $ix < $$num[0]; $ix++) {
		if ($ix % 2 == 0) {
		    for (my $iy = 0; $iy < $$num[1]; $iy++) {
			$pin_num++;
			my $pn = $$pin_name[$pin_num];
			if ($pnf || defined($pn) && $pn ne "" ) {
			    pin( $ix*$$sep[0]-$$orig[0], $iy*$$sep[1]-$$orig[1], $drill, $thickness[$it], $pn, "", $pin_num );
			}
		    }
		} else {
		    for (my $iy = $$num[1]-1; $iy >= 0 ; $iy--) {
			$pin_num++;
			my $pn = $$pin_name[$pin_num];
			if ($pnf || defined($pn) && $pn ne "" ) {
			    pin( $ix*$$sep[0]-$$orig[0], $iy*$$sep[1]-$$orig[1], $drill, $thickness[$it], $pn, "", $pin_num );
			}
		    }
		}
	    }
	} else {
	}
	if (defined($func)) {
	    &$func($data);
	} else {
	    silk_bb();
	}
	element_stop();
    }
}

sub pinlist_body($) {
    my $data = shift;
    my ($nx, $ny, $B) = @$data;

    # https://www.elfa.se/Web/Downloads/_t/ds/8266xx_x_eng_tds.pdf
    my $D = 1.3 + ($nx-1)/2 * 2.54;
    my $W = 2.8;
    my $Y = 2.54 * ($ny-1)/2;
    my $min = [  $D     , -$Y - 1.27 ];
    my $max = [  $D + $W,  $Y + 1.27 ];

    silk_bb();
    silk_width(0.12);

    silk_rect($min, $max, 0.12);
    #silk_start($bbx2 + $silk_default/2, -$Y);
    silk_start($D + $W, -$Y);
    silk_rline( $B, 0);
    if ($Y > 0) {
	silk_rline(0, 2*$Y);
	silk_rline(-$B, 0);
    }
    silk_width();
}
sub gen_pinlists() {
    my $Name = "hdr064";
    my $doc =
"# 0.635mm (25mil) sq. pin list, 2.54mm pitch
# AMPMODU MOD II Series https://www.elfa.se/Web/Downloads/_t/ds/8266xx_x_eng_tds.pdf
# p.G7-G14 http://www.fischerelektronik.de/fileadmin/fischertemplates/download/Katalog/connectors.pdf
# Harwin M20, p.212-215 https://cdn.harwin.com/pdfs/Harwin_Product_Catalog.pdf
";
    my $sep = [ 2.54, 2.54 ];
    my $N = 36+1;
    my $lead_dia = $s2 * 0.635;
    my $drill = lead_to_drill($lead_dia);


    for (my $iy = 1; $iy < $N; $iy++) {
	my $name = sprintf("%s_%02dx%02d", $Name, 1, $iy);
	gen_pin_matrix($name, $doc, "y", $sep, [ 1, $iy ], $drill);
    }
    for (my $iy = 1; $iy < $N; $iy++) {
	my $name = sprintf("%s_%02dx%02d", $Name, 2, $iy);
	gen_pin_matrix($name, $doc, "y", $sep, [ 2, $iy ], $drill);
    }

    for (my $iy = 1; $iy < $N; $iy++) {
	my $name = sprintf("%sR_%02dx%02d", $Name, 1, $iy);
	my $data = [ 1, $iy, 7 ];
	gen_pin_matrix($name, $doc, "y", $sep, [ 1, $iy ], $drill, undef, undef, \&pinlist_body, $data);
    }

    for (my $iy = 1; $iy < $N; $iy++) {
	my $name = sprintf("%sR_%02dx%02d", $Name, 2, $iy);
	my $data = [ 2, $iy, 7 ];
	gen_pin_matrix($name, $doc, "y", $sep, [ 2, $iy ], $drill, undef, undef, \&pinlist_body, $data);
    }
}
#gen_pinlists();

sub gen_relay_carlo_gavassi() {
    my $name = "carlo_gavazzi_M25A001xx";
    my $doc  =
"# Miniature Relay Series M25 - 1 pole 16A, monostable
# http/www1.elfa.se/data1/wwwroot/assets/datasheets/03708062.pdf\n";
    my $lead_a   = triangle_r(0.5,0.5);
    my $drill_a  = lead_to_drill($lead_a);
    my @th_a     = drill2thickness($drill_a);
    my $lead_pwr = triangle_r(0.5,0.8);
    my $drill_pwr= lead_to_drill($lead_pwr);
    my @th_pwr   = drill2thickness($drill_pwr);
    my $xdim = 29;
    my $ydim = 12.7;
    my $r = 0.5;
    my $min = [ -12.5-2.4, -$ydim/2 ];
    my $max = vec_add($min, [$xdim, $ydim]);
    $pr_save = "";
    pr_inc();
    pr("  # body\n");
    silk_rect($min, $max, $r);
    pr_dec();
    my $body = $pr_save;
    for (my $ix = 0; $ix < @th_a; $ix++) {
	my $file = sprintf("%s_%s.fp", $name, thickness_suffix($ix));
	my $th_a   = $th_a[$ix];
	my $th_pwr = $th_pwr[$ix];
	element_start($file, $doc);
	# mark is at center of all pins
	pin( -12.5, -3.75, $drill_a, $th_a, "A2", "square", "A2");
	pin( -12.5,  3.75, $drill_a, $th_a, "A1", "", "A1");
	pin(   2.5, -3.75, $drill_pwr, $th_pwr, "12", "", 12);
	pin(   2.5,  3.75, $drill_pwr, $th_pwr, "12", "", 12);
	pin(   7.5, -3.75, $drill_pwr, $th_pwr, "11", "", 11);
	pin(   7.5,  3.75, $drill_pwr, $th_pwr, "11", "", 11);
	pin(  12.5, -3.75, $drill_pwr, $th_pwr, "14", "", 14);
	pin(  12.5,  3.75, $drill_pwr, $th_pwr, "14", "", 14);
	pr($body,1);
	element_stop();
    }
}
#gen_relay_carlo_gavassi();

sub gen_Schrack_RT() {
    my $name = "schrack_RT";
    my $doc =
'# TE Genereal Purpose Relays, Power PCB Relay RT1 (1 pole) and RT2 (2 pole) series
# RT1 http://www.farnell.com/datasheets/1869190.pdf
# RT2 http://www.tycoelectronics.com/commerce/DocumentDelivery/DDEController?Action=srchrtrv&DocNm=RT2&DocType=Data+Sheet&DocLang=English
';

    my @version = (
	# version, Ampere, pinning/pitch, no.of pins for func. 11 12 and 14, @form index
	[ "1", 12, 3.50, 1, 0 ],
	[ "2", 12, 5.04, 1, 0 ],
	[ "3", 16, 5.04, 2, 0 ],
	[ "4",  8, 5.04, 1, 1 ],
	[ "B", 12, 3.50, 1, 0 ],
	[ "D", 16, 5.04, 2, 0 ],
	[ "E",  8, 5.04, 1, 1 ],
    );
    my @form = ( # or "contact arrangement"
	[
	    [ 1, "C"], # C is "changeover contact"
	    [ 3, "A"], # A is "closing contact only"
	], [
	    [ 2, "C"], # C is "changeover contact"
	    [ 4, "A"], # A is "closing contact only"
	],
    );
    my $xdim = 29;
    my $ydim = 12.7;
    my $cx = 1.5 * 5.04;
    my $r = 0.5;
    my $x1 = 22.65;
    my $x2 = 20.3;
    my $y1 = 7.5;
    my $drill = 1.3;
    my @th = drill2thickness($drill);
    my $min = [ $cx-$x1, -$ydim/2 ];
    my $max = vec_add($min, [$xdim, $ydim]);
    $pr_save = "";
    pr_inc();
    pr("  # body\n");
    silk_rect($min, $max, $r);
    pr_dec();
    my $body = $pr_save;

    for (my $ix = 0; $ix < @version; $ix++) {
	my $V = $version[$ix][0];
	my $A = $version[$ix][1];
	my $P = $version[$ix][2];
	my $N = $version[$ix][3];
	my $I = $version[$ix][4];

	for (my $fx = 0; $fx < @{$form[$I]}; $fx++) {
	    my $CA = $form[$I][$fx][0]; # contact arrangement number
	    my $F  = $form[$I][$fx][1]; # form letter
	    for (my $ix = 0; $ix < @th; $ix++) {
		my $file = sprintf("%s%s%1d4xxx_%s.fp", $name, $V, $CA, thickness_suffix($ix));

		element_start($file, $doc);

		# mark is at center of all pins
		pin( $cx-$x2, -3.75, $drill, $th[$ix], "A2", "square", "A2");
		pin( $cx-$x2,  3.75, $drill, $th[$ix], "A1", "", "A1");
		# pin A2
		if ($F eq "C" ) {
		    pin( $cx-$P, -3.75, $drill, $th[$ix], "22", "", 22) if ($I == 1);
		    pin( $cx-$P, -3.75, $drill, $th[$ix], "12", "", 12) if ($N == 2);
		    pin( $cx-$P,  3.75, $drill, $th[$ix], "12", "", 12);
		}
		if ($I == 1) {
		    pin( $cx, -3.75, $drill, $th[$ix], "21", "", 21);
		    pin( $cx,  3.75, $drill, $th[$ix], "11", "", 11);
		} else {
		    pin( $cx, -3.75, $drill, $th[$ix], "11", "", 11);
		    pin( $cx,  3.75, $drill, $th[$ix], "11", "", 11) if ($N == 2);
		}

		pin( $cx+$P, -3.75, $drill, $th[$ix], "24", "", 24) if ($I == 1);
		pin( $cx+$P, -3.75, $drill, $th[$ix], "14", "", 14) if ($N == 2);
		pin( $cx+$P,  3.75, $drill, $th[$ix], "14", "", 14);

		pr($body,1);
		element_stop();
	    }
	}
    }

}
#gen_Schrack_RT();

sub gen_DIP() {
    my $Name = "DIP";
    my $sep = [ 3*2.54, 2.54 ];

# mo-001b.pdf .3 8 16
# mo-001d.pdf .3 14 16
# MO-001f.pdf .3
# Mo-015g.pdf .6 24 40 42 32
# Mo-016d.pdf .9 36 50 52 64
# Mo-024c.pdf .5 24
# Mo-026d.pdf .4 24 28 30 32 36 32 22
# Mo-043a.pdf .75 64
# Mo-095a.pdf .3 8 14 16 18 20 22 24 28 32
# Mo-122a.pdf .3 14 16 20

    my @sz = ( 8,    14,    16,    18,    20,    22,    24,    28,    32);
    my @D  = ( 9.27, 16.89, 19.43, 21.97, 24.51, 27.05, 29.59, 34.67, 39.75);
    my $E1 = 7.24;
    #my $B = 0.46;
    #my $C = 0.25;
    #my $lead_max = triangle_r( 0.56, 0.38 ); 0.676756972627545
    my $lead_dia = triangle_r( 0.46, 0.25 ); # 0.523545604508337
    #my $drill_max = lead_to_drill($lead_max); 0.9
    #my $drill_mid = lead_to_drill($lead_mid); 0.8
    #print "$lead_mid $lead_max $drill_mid $drill_max\n";
    my $drill = lead_to_drill($lead_dia);
    for my $sz (@sz) {
	my $doc  = "# http://www.jedec.org/  Mo-095a.pdf\n";
	my $name = sprintf("jedec_%s%02d", $Name, $sz);
	gen_pin_matrix($name, $doc, "d", $sep, [ 2, $sz/2 ], $drill);
    }
    for my $sz ((2, 4, 6)) {
	my $doc  = "# Mo-095a extrapolated\n";
	my $name = sprintf("%s%02d", $Name, $sz);
	gen_pin_matrix($name, $doc, "d", $sep, [ 2, $sz/2 ], $drill);
    }
}
#gen_DIP();

sub gen_DE117_xx_x0() {
    my $name = "DE117_xx_x0";
    my $doc =
"# https://www.display-elektronik.de/filter/DE117-TS-20_75.pdf
# the pin width isn't stated in the doc, it measures to 0.4-0.45mm
";
    my @pin_name = qw/ _ BP 1E 1D 1C DP1 2E 2D 2C DP2 3E 3D 3C DP3 4E 4D 4C
			 4B 4A 4F 4G 3B  3A 3F 3G 2B  2A 2F 2G 1B  1A 1F 1G /;
    my $data = [ 16.8, 23.9, 6, 0.6, 1.6 ];
    my $pin_w = [0.43, 0.3];
    my $lead_dia = vec_length($pin_w);
    my $drill = lead_to_drill($lead_dia);

    gen_pin_matrix($name, $doc, "d", [17.1, 1.27], [2, 16], $drill, undef, \@pin_name, \&pkg_body_lcd, $data);

    my $file = "${name}_pad.fp";
    element_start($file, $doc);
    shift @pin_name;
    pkg_rect_pads([0, @pin_name/2], [$$data[0]/2 - 1, $$data[1]/2], [ 1.27, 0.5, 3.0], undef, \@pin_name);
    pkg_body_lcd($data);
    element_stop();
}
#gen_DE117_xx_x0();

sub gen_lcd_unknown00() {
    my $name = "lcd_unknown00";
    my $doc = "";
    my @pin_name = qw/ _  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 /;
    my $data = [ 32, 48, 8, 0.5, 1.6 ];
    my $pin_w = [0.3, 0.52];
    my $lead_dia = vec_length($pin_w);
    my $drill = lead_to_drill($lead_dia);

    gen_pin_matrix($name, $doc, "d", [32.2, 2.54], [2, 13], $drill, undef, \@pin_name, \&pkg_body_lcd, $data);
}
#gen_lcd_unknown00();

sub gen_OHK1P0703CS1() {
    my $name = "backlight_OHK1P0703CS1";
    my $doc = "";

    my $x = 41/2;
    my $y = 3*2.54/2;
    my $body = [47.9, 27.8];
    my $lead = 0.5;
    my $drill  = lead_to_drill($lead);
    my @th     = drill2thickness($drill);

    for (my $ix = 0; $ix < @th; $ix++) {
	my $file = sprintf("%s_%s.fp", $name, thickness_suffix($ix));
	my $th   = $th[$ix];
	element_start($file, $doc);
	# mark is at center of body
	pin( -$x, -$y, $drill, $th, "A", undef, 2);
	pin( -$x,  $y, $drill, $th, "K", undef, 1);
	pin(  $x, -$y, $drill, $th, "K", undef, 1);
	pin(  $x,  $y, $drill, $th, "A", undef, 2);
	my @bbw = bb_enlarge($silk_w/2, @bounding_box);
	silk_crect($origin, $body, 0, \@bbw);
	element_stop();
    }
}
#gen_OHK1P0703CS1();

sub gen_XP_JWK25() {
    my @data_s = qw / +Vin -Vin +Vout Trim   -Vout Enable /;
    my @data_d = qw / +Vin -Vin +Vout Common -Vout Enable /;
    my @pos = (
	[   2.54,  20.3/2 ],
	[  -2.54,  20.3/2 ],
	[  10.16, -20.3/2 ],
	[   0.00, -20.3/2 ],
	[ -10.16, -20.3/2 ],
	[ -10.16,  20.3/2 ],
    );

    my $name = "xppower_jwk25";
    my $doc  =
"# XP DC-DC Converter 25W
# http://www.farnell.com/datasheets/2061959.pdf
";
    my $lead   = 1.00;
    my $drill  = lead_to_drill($lead);
    my @th     = drill2thickness($drill);
    my $xdim = 25.4;
    my $ydim = $xdim;
    my $r = 1.0;
    my $min = [ -$xdim/2, -$ydim/2 ];
    my $max = [  $xdim/2,  $ydim/2 ];
    $pr_save = "";
    pr_inc();
    pr("  # body\n");
    silk_rect($min, $max, $r);
    pr_dec();
    my $body = $pr_save;
    for my $type (qw/ s d /) {
	my $r = \@data_s;
	if ($type eq "d") {
	    $r = \@data_d;
	}
	for (my $ix = 0; $ix < @th; $ix++) {
	    my $file = sprintf("%s%s_%s.fp", $name, $type, thickness_suffix($ix));
	    my $th   = $th[$ix];
	    element_start($file, $doc);
	    # mark is at center of body
	    for (my $ix = 0; $ix < @pos; $ix++) {
		my $x = $pos[$ix][0];
		my $y = $pos[$ix][1];
		my $pn = $$r[$ix];
		pin( $x, $y, $drill, $th, $pn);
	    }
	    pr($body,1);
	    element_stop();
	}
    }
}
#gen_XP_JWK25();

###########

sub gen_vishay_trimcap_8x9() {
    element_start("vishay_trimcap_8x9.fp",
"# a surplus 2-18pF trim capacitor I got from Elfa
");

    pin( -4, 0, 1.2, 2.7);
    pin(  4, 0, 1.2, 2.7);
    silk_start(-4  , -4);
    silk_rline( 0  ,  8);
    silk_rline( 9  ,  0);
    silk_rline( 0  , -8);
    silk_rline(-9  ,  0);
    silk_width(0.18);
    silk_circle( [0,0], 7.5/2 );
    silk_circle( [0,0], 2.5/2 );
    my $b = 0.96 * sqrt(2) * 2.5 / 4;
    silk_start( -$b - 0.2, $b - 0.2 );
    silk_rline( 2*$b, - 2 * $b);
    silk_start( -$b + 0.2, $b + 0.2 );
    silk_rline( 2*$b, - 2 * $b);
    silk_width(0.32);
    element_stop();
}
#gen_vishay_trimcap_8x9();

sub gen_johansson_antennas() {
    my $name = "johanson_antenna";
    my $doc = "# http://www.johansontechnology.com/datasheets";
    my ($f, $n, $g ) = ( "Feeding point", "NC", "GND" );

    my @data = (
	# id body:[ L W ] [pinnumbers] [names]
	#   [ px py cx cy ] ...
	[ "2450AT42E010B", [2,5], [1,2,4,3], [ "", $f, $n, $g, $g ],
	  [ 0.6, 1.5, [ -0.8, 0.8 ], [-1.75, 1.75] ],
        ],
	[ "2450AT42B100" , [2,5], [1,2,3,4], [ "", $f, $n, $n, $n ],
	  [ 2.0, 1.0, [ 0 ], [ -2.6, 2.6] ],
	  [ 0.7, 2.8, [ -0.85, 0.85 ], [ 0 ] ],
        ],
    );


    for my $r (@data) {
	my ($id, $body, $pnum, $pname, @pad ) = @$r;
	my $file = "${name}_$id.fp";
	my $Doc = "$doc/$id/$id.pdf";
	my $ix = 0;
	element_start($file, $Doc);
	my @arr = ();
	for my $p (@pad) {
	    my ($px, $py, $ax, $ay) = @$p;
	    for my $cx (@$ax) {
		for my $cy (@$ay) {
		    my $pin = $$pnum[$ix];
		    #print "$pin: $$pname[$pin]\n";
		    push @arr, [ $pin, $cx, $cy, $px, $py ];
		    $ix++;
		}
	    }
	}
	for my $r (sort { $$a[0] <=> $$b[0] } @arr) {
	    my ($pin, $cx, $cy, $px, $py) = @$r;
	    pad( $cx, $cy, $px, $py, $$pname[$pin], undef, 0, $pin);
	}

	my @bbw = bb_enlarge($silk_w/2, @bounding_box);
	silk_crect($origin, $body, 0, \@bbw);
	element_stop();
    }
}
#zgen_johansson_antennas();

sub gen_johanson_x2y() {
    my $name = "johanson_x2y";
    my $doc  = "# https://www.johansondielectrics.com/downloads/jdi-x2y-pcb-design-guide.pdf\n";
    my $desc = "X2Y filter & decoupling capacitors";
    my @pin_name = qw/ A B G /;

    my $str = 
"   0402 (X07)  0603 (X14)  0805 (X15)  1206 (X18)  1210 (X41)  1410 (X44)  1812 (X43)
    IN    MM    IN    MM    IN    MM    IN    MM    IN    MM    IN    MM    IN    MM

L   0.045 1.143 0.064 1.626 0.080 2.032 0.124 3.150 0.125 3.175 0.140 3.556 0.174 4.420
    0.003 0.076 0.005 0.127 0.008 0.203 0.010 0.254 0.010 0.254 0.010 0.254 0.010 0.254

W   0.025 0.635 0.035 0.889 0.050 1.270 0.063 1.600 0.098 2.489 0.098 2.490 0.125 3.175
    0.003 0.076 0.005 0.127 0.008 0.203 0.010 0.254 0.010 0.254 0.010 0.254 0.010 0.254

T   0.020 0.508 0.026 0.660 0.040 1.016 0.050 1.270 0.070 1.778 0.070 1.778 0.090 2.286
    max   max   max   max   max   max   max   max   max   max   max   max   max   max

EB  0.008 0.203 0.010 0.254 0.012 0.305 0.016 0.406 0.018 0.457 0.018 0.457 0.022 0.559
    0.003 0.076 0.006 0.152 0.008 0.203 0.010 0.254 0.010 0.254 0.010 0.254 0.012 0.305

CB  0.012 0.305 0.018 0.457 0.022 0.559 0.040 1.016 0.045 1.143 0.045 1.143 0.045 1.143
    0.003 0.076 0.004 0.102 0.005 0.127 0.005 0.127 0.005 0.127 0.005 0.127 0.005 0.127

X   0.51 0.89 1.27 1.65 2.54 2.54 3.18
Y   0.45 0.64 0.89 1.02 1.02 1.02 1.02
G   0.71 1.02 1.27 2.03 2.03 2.54 3.30
V   0.33 0.51 0.56 1.02 1.14 1.14 1.14
U   0.99 1.52 2.03 3.05 4.06 4.06 4.83
Z   1.63 2.29 3.05 4.06 4.06 4.57 5.33
";
    my @line = split(/\n/, $str);
    my $hdr = shift @line;
    $hdr =~ s/\(//g;
    $hdr =~ s/^ *//;
    my @hdr = split(/\) */, $hdr);
    my @sz = ();
    for my $ss (@hdr) {
	my ($ssz, $sso) = split(/ +/, $ss);
	push @sz, $sso;
    }

    my @data;
    my @lbl;
    my $dx = 0;
    for (my $ix = 0; $ix < @line; $ix++) {
	next if ($line[$ix] =~ m/^$/);
	next if ($line[$ix] !~ m/^([A-Z]+)/);

	my @tmp = split(/ +/, $line[$ix]);
	my $tag = shift @tmp;
	$lbl[$dx] = $tag;
	if (@tmp ==  @sz) {
	} else {
	    my @ix = @{vec_sadd(1,vec_mul(2,[(0..$#sz)]))};
	    @tmp = @tmp[@ix];
	}
	for (my $sx = 0; $sx < @sz; $sx++) {
	    $data[$sx][$dx] = $tmp[$sx];
	}
	$dx++;
    }

    #print "lbl: ", join(" ", @lbl), "\n";
    for (my $sx = 0; $sx < @sz; $sx++) {
	my ($L, $W, $T, $EB, $CB, $X, $Y, $G, $V, $U, $Z) = @{$data[$sx]};
	#print "$sz[$sx]: ", join(" ", @{$data[$sx]}), "\n";

	my $file = $name . "_" . $sz[$sx] . ".fp";

	element_start($file,$doc,$desc,"C?",$sz[$sx]);
	my $x = ($Z - $Y)/2;
	my $y = 0;
	pad(-$x, $y, $Y, $X, "A", undef, 0, 1);
	pad( $x, $y, $Y, $X, "B", undef, 0, 2);
	pad( 0,   0, $V, $U, "G", undef, 0, 3);

	my @bbw = bb_enlarge($silk_w/2, @bounding_box);
	$W = $X + 2*$mask_gap + $silk_w*1.01;
	silk_crect($origin, [$L, $W], 0, \@bbw);
	#silk_crect($origin, [$L, $W], 0);

	element_stop();
    }

}
#gen_johanson_x2y();

sub gen_alps_290016() {
  element_start("alps_290016.fp", "# Alps RK09K1130 potensiometer
# http://www.farnell.com/datasheets/317980.pdf
# http://www.farnell.com/datasheets/317981.pdf
");
  my $y = 1;
  pin( -2.5, $y, 1.0, 2.0 );
  pin(  0.0, $y, 1.0, 2.0 );
  pin(  2.5, $y, 1.0, 2.0 );
  pin( -5.3, $y+7, 2.0, 4.0 );
  pin(  5.3, $y+7, 2.0, 4.0 );
  pr("\n");
  $bby2 = $y+7+5.5;
  silk_bb(0.32);
  element_stop();
}
#gen_alps_290016();

sub gen_bourns_ptv09() {
    my $bx = 10.0;
    my $drill = 1.0;
    my $px = 5.0/2;
    my $mdrill = 2.3;
    my @thickness = drill2thickness($drill);

    my $name = "bourns_ptv09a";
    my $doc = "# https://www.bourns.com/docs/Product-Datasheets/PTV09.pdf\n";

    for (my $tx = 0; $tx < @thickness; $tx++) {
	my $limit_radius = $thickness[$tx] + $mask_gap;
	if ($px < $limit_radius) { next; }

	my $file = $name . thickness_suffix($tx) . "-horz.fp";
	element_start($file, $doc);
	my $py = 7.0;
	my $pm = 10.0;
	for (my $ix = -1; $ix <= 1; $ix++) { pin( $ix * $px, $py, $drill, $thickness[$tx]); }
	pin(-$pm/2, 0, $mdrill, $mdrill+1.5, "M", "", "M");
	pin( $pm/2, 0, $mdrill, $mdrill+1.5, "M", "", "M");
	my @bbw = bb_enlarge($silk_w/2, @bounding_box);
	silk_rect([-5,-5.5], [5,6.5], 0, \@bbw);
	element_stop();
    }

    for (my $tx = 0; $tx < @thickness; $tx++) {
	my $limit_radius = $thickness[$tx] + $mask_gap;
	if ($px < $limit_radius) { next; }

	my $file = $name . thickness_suffix($tx) . "-vert.fp";
	element_start($file, $doc);
	my $py = 5.0;
	my $pm = 8.2;
	for (my $ix = -1; $ix <= 1; $ix++) { pin( $ix * $px, $py, $drill, $thickness[$tx]); }
	pin(-$pm/2, 0, $mdrill, $mdrill+1.5, "M", "", "M");
	pin( $pm/2, 0, $mdrill, $mdrill+1.5, "M", "", "M");
	my @bbw = bb_enlarge($silk_w/2, @bounding_box);
	silk_rect([-5,0], [5,6.8+1.2], 0, \@bbw);
	silk_width(0.18);
	silk_rect([-3,6.8+1.2], [3,20], 0, \@bbw);
	silk_width();
	element_stop();
    }

}
#gen_bourns_ptv09();

sub gen_nikkai_gwp() {
  element_start("nikkai_gwp.fp", "# Nikkay Ultra-Thin Rocker switch
# GW12xxP (P = straight)
# GW22xxP
# http://www.farnell.com/datasheets/9827.pdf
");
  $bbx1 = -7.5/2;
  $bbx2 = -$bbx1;
  $bby1 = 0;
  $bby2 = 5;
  my $y = 2.5-1.27;
  pin( -2.54, $y, 0.6, 1.1 );
  pin(  0.00, $y, 0.6, 1.1 ); # on GW22
  pin(  2.54, $y, 0.6, 1.1 );
  $y += 2.54;
  pin( -2.54, $y, 0.6, 1.1 );
  pin(  0.00, $y, 0.6, 1.1 );
  pin(  2.54, $y, 0.6, 1.1 );
  silk_bb(0.32);
  element_stop();
}
#gen_nikkai_gwp();

sub gen_te_fsmxjxh() {
    my $name = "te_FSMxJxH";
    my $doc =
"# http://www.farnell.com/datasheets/29689.pdf
# 6 mm tactile switch, through hole, high temperatur
";

    my $drill = 1.00; # 0.99
    my @thickness = drill2thickness($drill);
    my $dx = 6.50/2;
    my $dy = 4.50/2;

    $round_first_pin = 1;


    for (my $ix = 0; $ix < @thickness; $ix++) {
	my $file = sprintf("%s_%s.fp", $name, thickness_suffix($ix));
	my $limit_radius = $thickness[$ix]/2 + $mask_gap;
	if ($dy < $limit_radius) {
	    #warn "$file: too close spacing <$spacing $limit_radius";
	    next;
	}
	my $th = $thickness[$ix];

	element_start($file, $doc);
	pin( -$dx, -$dy, $drill, $th, 1, "", 1);
	pin(  $dx, -$dy, $drill, $th, 1, "", 1);
	pin( -$dx,  $dy, $drill, $th, 2, "", 2);
	pin(  $dx,  $dy, $drill, $th, 2, "", 2);
	silk_width(0.12);
	silk_circle([0,0], 3.51/2);
	silk_width();
	silk_sq(5.99);
	element_stop();

    }
    $round_first_pin = 0;
}
#gen_te_fsmxjxh();

sub gen_multicomp_2MSxM2RE() {
    my $name = "multicomp_2MSxM2RE";
    my $doc =
"# http://www.farnell.com/datasheets/1375607.pdf
# sub-miniature toggle switch, 1 pole (SP)
";

    my $drill = 1.10; # 1.09
    my @thickness = drill2thickness($drill);
    my $dx = 0;
    my $dy = 2.54;
    $round_first_pin = 1;

    for (my $ix = 0; $ix < @thickness; $ix++) {
	my $file = sprintf("%s_%s.fp", $name, thickness_suffix($ix));
	my $limit_radius = $thickness[$ix]/2 + $mask_gap;
	if ($dy/2 < $limit_radius) {
	    #warn "$file: too close spacing <$spacing $limit_radius";
	    next;
	}
	my $th = $thickness[$ix];

	element_start($file, $doc);
	pin( 0, -$dy, $drill, $th, 1, "", 1);
	pin( 0,    0, $drill, $th, 2, "", 2);
	pin( 0,  $dy, $drill, $th, 3, "", 3);

	silk_circle([0,0], 6/2);
	silk_crect([0,0], [5.08,8.13],0);
	element_stop();

    }
    $round_first_pin = 0;
}
#gen_multicomp_2MSxM2RE();

sub gen_aliexpress_cloukeu_4x4() {
    my $name = "aliexpress_cloukeu_4x4";
    my $doc =
"# http://aliexpress.com 50Pcs-Copper-SMD-4x4-Tact-Push-Button-Switch-4-4-1-5MM-1-6-1-7.jpg_q50.jpg
";

    my $dx = (8.0 + 4.4)/4;
    my $dy = (4.8 + 2.6)/4;
    my $px = (8.0 - 4.4)/2;
    my $py = (4.8 - 2.6)/2;
    my $cr = ipc_corner($py);

    my $file = "$name.fp";
    element_start($file, $doc);
    pad(-$dx, -$dy, $px, $py, undef, "", $cr);
    pad( $dx, -$dy, $px, $py, undef, "", $cr);
    pad(-$dx,  $dy, $px, $py, undef, "", $cr);
    pad( $dx,  $dy, $px, $py, undef, "", $cr);

    my @bbw = bb_enlarge($silk_w/2,@bounding_box);
    silk_circle([0,0], 2/2);
    silk_crect([0,0], [5.2,5.2],-1, \@bbw);
    element_stop();
}
#gen_aliexpress_cloukeu_4x4();

sub gen_nikkai_D2() {
    my $pfx = "nikkai_D220";
    my $doc = "# http://www.farnell.com/datasheets/70399.pdf\n";
    my $lead = 0.8;
    my $drill = lead_to_drill($lead);
    my @thickness = drill2thickness($drill);

    my $dx = 5.08;
    my $dy = 5.08;
    #$round_first_pin = 1;

    my @pole = (1, 2, 4);
    my @bw   = (7, 12.4, 22.6);

    for (my $ix = 0; $ix < @pole; $ix++) {
	my $poles = $pole[$ix];
	my $bw = $bw[$ix];
	my $name = sprintf "%s%sxP", $pfx, $poles;

	$pr_save = "";
	pr_inc();

	pr("\n");
	pr("# Mounting\n");
	silk_width(0.25);
	silk_circle_notch($origin, 6.5/2, 5.6 - 6.5/2, 0.6, -90);
	silk_circle([0, -6.5], 2.2/2);
	pr("# Locking ring (AT507M, p2-06)\n");
	silk_width(0.12);
	silk_start(0,-6.5+2.2/2);
	silk_line(0,-6.5-2.2/2);
	silk_start(-2.2/2,-6.5);
	silk_rline(2.2,0);

	pr("\n");
	pr("# Outline\n");
	silk_width(0.32);
	silk_crect([0,0], [$bw,14.4], 0);

	pr_dec();
	my $body = $pr_save;

	for (my $ix = 0; $ix < @thickness; $ix++) {
	    my $file = sprintf("%s_%s.fp", $name, thickness_suffix($ix));
	    my $limit_radius = $thickness[$ix]/2 + $mask_gap;
	    if ($dy/2 < $limit_radius) {
		#warn "$file: too close spacing <$spacing $limit_radius";
		next;
	    }
	    my $th = $thickness[$ix];

	    element_start($file, $doc);
	    my $pn = 1;
	    my $offs = -($poles-1)*$dx/2;
	    for (my $p = 0; $p < $poles; $p++) {
		my $x = $offs + $p * $dx;
		pin( $x,  $dy, $drill, $th, $pn, "", $pn); $pn++;
		pin( $x,    0, $drill, $th, $pn, "", $pn); $pn++;
		pin( $x, -$dy, $drill, $th, $pn, "", $pn); $pn++;
	    }
	    pr($body,1);
	    element_stop();
	}
    }
}
#gen_nikkai_D2();

sub gen_bulgin_ledholder() {
    # for T1 5mm leds
    my $prefix = "bulgin";
    my $doc = "# p362 http://www.bulgin.com/media/import/Bulgin_Catalogue_High_Quality.pdf\n";
    my $drill = lead_to_drill(0.5,0.5);
    my @thickness = drill2thickness($drill);

    my $dy = 2.54/2;
    my $or = 5.9/2;
    my $ir = 5.0/2;
    my @pin_name = ( "Cathode", "Anode" );
    my $mark = 1;

    my @data = (
	#  name   od, bore hole
	[ "A104800",  7.6, 6.3 ],
	[ "A10480A",  9.5, 8.0 ],
	[ "A10500A", 10.0, 8.0 ],
    );

    for my $r (@data) {
	my ($part, $od, $bh) = @$r;

	$pr_save = "";
	pr_inc();

	pr("\n");
	pr("# Outline/Mounting\n");
	silk_circle($origin, $od/2);
	silk_circle_flat($origin, $or, $ir, 90);

	silk_width(0.12);
	#silk_circle($origin, $bh/2);
	silk_circle($origin, $ir);
	silk_start(-$mark,0);
	silk_rline(2*$mark,0);
	silk_start(0,-$mark/2);
	silk_rline(0,$mark);
	silk_width();

	pr_dec();
	my $body = $pr_save;

	for (my $ix = 0; $ix < @thickness; $ix++) {
	    my $file = sprintf("%s_%s_%s.fp", $prefix, $part, thickness_suffix($ix));
	    my $limit_radius = $thickness[$ix]/2 + $mask_gap;
	    if ($dy < $limit_radius) {
		#warn "$file: too close spacing <$spacing $limit_radius";
		next;
	    }
	    my $th = $thickness[$ix];

	    element_start($file, $doc);
	    pin(    0,  $dy, $drill, $th, $pin_name[0]);
	    pin(    0, -$dy, $drill, $th, $pin_name[1]);
	    pr($body,1);
	    element_stop();
	}
    }
}
#gen_bulgin_ledholder();

sub gen_sternice_p13vpe() {
    my $name = "sternice_P13VPE";
    my $doc = "# http://www.farnell.com/datasheets/70399.pdf\n";
    my $drill = lead_to_drill(1.6,0.5);
    my @thickness = drill2thickness($drill);

    my $dx = 2.7;
    my $dy = 5.08;

    $pr_save = "";
    pr_inc();

    pr("\n");
    pr("# Mounting\n");
    silk_width(0.25);
    silk_circle($origin, 10/2);
    silk_circle([0, -7], 1/2);
    silk_width(0.12);
    silk_start(0,5);
    silk_line(0,-7.5);
    silk_start(-0.5,-7);
    silk_rline(1,0);
    silk_start(-5,0);
    silk_rline(10,0);

    pr("\n");
    pr("# Outline\n");
    silk_width(0.32);
    silk_circle($origin, 16/2);

    pr_dec();
    my $body = $pr_save;

    for (my $ix = 0; $ix < @thickness; $ix++) {
	my $file = sprintf("%s_%s.fp", $name, thickness_suffix($ix));
	my $limit_radius = $thickness[$ix]/2 + $mask_gap;
	if ($dx < $limit_radius) {
	    #warn "$file: too close spacing <$spacing $limit_radius";
	    next;
	}
	my $th = $thickness[$ix];

	element_start($file, $doc);
	pin( -$dx,  2.8, $drill, $th, 1);
	pin(    0, -2.2, $drill, $th, 2);
	pin(  $dx,  2.8, $drill, $th, 3);
	pr($body,1);
	element_stop();
    }
}
#gen_sternice_p13vpe();

sub gen_alps_SKHCBxA010() {
    element_start("alps_SKHCBxA010.fp", "# Alps Tact 12mm Square (Snap-in Type)
# http://www.alps.com/WebObjects/catalog.woa/E/PDF/Tact/SnapIn/SKHC/SKHC.PDF
");
    pin( -12.5/2, -5/2, 1.2, 2.5, "1" );
    use_same_pin_no();
    pin(  12.5/2, -5/2, 1.2, 2.5, "2" );
    pin( -12.5/2,  5/2, 1.2, 2.5, "3" );
    use_same_pin_no();
    pin(  12.5/2,  5/2, 1.2, 2.5, "4" );

    pr("\n");
    pr("# Plastic guide bosses\n");
    pr("Pin [ 0mm -4.500mm  1.7mm 0.0mm 0.0mm 1.7mm \"guide\" \"3\" \"\" ]\n");
    pr("Pin [ 0mm  4.500mm  1.7mm 0.0mm 0.0mm 1.7mm \"guide\" \"4\" \"\" ]\n");

    pr("\n");
    pr("# Knob\n");
    silk_width(0.25);
    silk_crect([0,0], [10,10], 1);

    pr("\n");
    pr("# Outline\n");
    silk_width(0.32);
    silk_crect([0,0], [12,12], 1, undef, 1);
    silk_start(-5,6);
    silk_rline(1,0);
    silk_rline(0,-0.5);
    silk_rline(2,0);
    silk_rline(0,0.5);
    silk_rline(7,0);
    element_stop();
}
#gen_alps_SKHCBxA010();

sub mk_vishay_mkt368($$$$$$$$) {
    my $volt = shift;
    my $P = shift;
    my $dt = shift;
    my $C = shift;
    my $w = shift;
    my $h = shift;
    my $l = shift;
    my $catalog = shift;

    my $name = "vishay_mkt368";
    my $doc = "# http://www.vishay.com/docs/28132/mkt368.pdf
# $volt V, pitch $P, lead dia $dt, Cap $C, width $w, height $h, length $l, catalog number 2222 368 $catalog
";

    #print "$volt V, pitch $P, lead dia $dt, Cap $C, width $w, height $h, length $l, catalog number 2222 368 $catalog\n";
    #return;
    my $file = sprintf("%s_%03dV_%suF.fp", $name, $volt, $C ) ;
    my $drill = 1.3;
    if ($dt == 0.6) {
	$drill = 1.0;
    }

    my $cu_dia = int(10 * $drill * 1.3 + 5) / 10;
    element_start($file, $doc);
    pin(  0, 0, $drill, $cu_dia, "");
    pin( $P, 0, $drill, $cu_dia, "");
    silk_crect( [$P/2,0], [$l, $w], $w/3);
    element_stop();
}
sub parse_vishay_mkt368($$) {
    my $volt = shift;
    my $tbl = shift;

    my @arr = split(/\n/, $tbl);
    my $P = 0;
    my $dt = 0;
    my $C = 0;
    my $w = 0;
    my $h = 0;
    my $l = 0;
    my $catalog = 0;

    for (@arr) {
	tr/ \t\r\n/ /s;
	s/^ //;
	s/ $//;
	next if (m/^$/);
	if (m/^Pitch = ([0-9.]+).* dt = ([0-9.]+) /) {
	    $P = $1;
	    $dt = $2;
	    $C = 0;
	    $w = 0;
	    $h = 0;
	    $l = 0;
	    $catalog = 0;
	    next;
	}
	my @fld = split;

	if (@fld == 7) { # "          4.0 x 13.0 (15.0) x 12.5   0.4"
	    $w = $fld[0];
	    $h = $fld[2];
	    $l = $fld[5];
	    next;
	} elsif (@fld == 2) { # "0.056                                      25563"
	    $C = $fld[0];
	    $catalog = $fld[1];
	} elsif (@fld == 9) { # "0.082     3.7 x 12.7 (15.0) x 12.5   0.4   25823"
	    $C = $fld[0];
	    $w = $fld[1];
	    $h = $fld[3];
	    $l = $fld[6];
	    $catalog = $fld[8];
	} else {
	    #warn $_;
	    next;
	}
	next if ($C == 0);
	mk_vishay_mkt368( $volt, $P, $dt, $C, $w, $h, $l, $catalog);
    }
}
sub gen_vishay_mkt368() {
    my @tbl = ( # [ volt, "table from the pdf"
# C uF   wmax x hmax        x lmax   mass  catalog number
	[ 63, "
Pitch = 10.0 ± 0.4 mm; dt = 0.60 ± 0.06 mm
 0.22     4.2 x 13.2 (15.5) x 12.5   0.5   15224
 0.27     4.0 x 12.8 (15.5) x 12.5   0.5   15274
 0.33     4.3 x 13.1 (15.5) x 12.5   0.5   15334
 0.39     4.2 x 12.9 (15.5) x 12.5   0.5   15394
 0.47     4.3 x 13.4 (16.0) x 12.5   0.5   15474
 0.56     4.7 x 13.7 (16.0) x 12.5   0.5   15564
 0.68     5.1 x 14.1 (16.5) x 12.5   0.6   15684
 0.82     5.5 x 14.5 (17.0) x 12.5   0.6   15824
  1.0     6.0 x 15.0 (17.5) x 12.5   0.8   15105
" ],
	[ 100, "
Pitch = 10.0 ± 0.4 mm; dt = 0.60 ± 0.06 mm
          4.0 x 13.0 (15.0) x 12.5   0.4
0.056                                      25563
0.068                                      25683
0.082     3.7 x 12.7 (15.0) x 12.5   0.4   25823
 0.10     4.0 x 13.0 (15.0) x 12.5   0.4   25104
 0.12     4.3 x 13.3 (15.0) x 12.5   0.4   25124
 0.15     3.9 x 12.9 (15.0) x 12.5   0.4   25154
 0.18     4.2 x 13.2 (15.5) x 12.5   0.5   25184
 0.22     4.5 x 13.6 (16.0) x 12.5   0.5   25224
Pitch = 15.0 ± 0.4 mm; dt = 0.80 ± 0.08 mm
 0.33     5.0 x 14.0 (17.0) x 17.5   0.6   25334
 0.27                                      25274
 0.39                                      25394
          5.5 x 14.5 (17.5) x 17.5   0.7
 0.47                                      25474
 0.56                                      25564
 0.68     6.0 x 15.0 (18.0) x 17.5   0.9   25684
 0.82     6.5 x 15.5 (18.5) x 17.5   1.0   25824
  1.0     7.5 x 16.5 (19.5) x 17.5   1.3   25105
Pitch = 22.5 ± 0.4 mm; dt = 0.80 ± 0.08 mm
          6.0 x 18.0 (21.0) x 26.0   2.5
  1.2                                      25125
  1.5                                      25155
  1.8     7.0 x 19.0 (22.0) x 26.0   3.2   25185
  2.2     7.5 x 19.5 (23.0) x 26.0   3.5   25225
  2.7     8.5 x 21.5 (24.0) x 26.0   4.1   25275
  3.3     9.0 x 22.0 (24.5) x 26.0   4.5   25335
Pitch = 27.5 ± 0.4 mm; dt = 0.80 ± 0.08 mm
  3.9     9.0 x 22.0 (24.0) x 30.0   4.8   25395
  4.7     10.0 x 23.0 (25.0) x 30.0  5.5   25475
  5.6     11.0 x 24.0 (26.0) x 30.0  6.2   25565
  6.8     12.0 x 25.0 (27.0) x 30.0  6.8   25685
" ],
	[ 250, "
Pitch = 10.0 ± 0.4 mm; dt = 0.60 ± 0.06 mm
0.027     4.2 x 13.0 (15.0) x 12.5   0.4   45273
0.033     4.6 x 13.0 (15.0) x 12.5   0.5   45333
0.039     4.0 x 13.0 (15.0) x 12.5   0.4   45393
0.047     4.5 x 13.5 (15.5) x 12.5   0.5   45473
          4.6 x 13.5 (15.5) x 12.5   0.5
0.056                                      45563
0.068                                      45683
0.082     4.4 x 13.4 (16.0) x 12.5   0.5   45823
 0.10     4.7 x 13.7 (16.0) x 12.5   0.5   45104
Pitch = 15.0 ± 0.4 mm; dt = 0.80 ± 0.08 mm
          5.0 x 14.0 (17.0) x 17.5   0.6
 0.12                                      45124
 0.15                                      45154
 0.18     5.5 x 14.5 (17.5) x 17.5   0.7   45184
 0.22     6.0 x 15.0 (18.0) x 17.5   0.9   45224
 0.27     6.0 x 15.5 (18.5) x 17.5   1.0   45274
 0.33     6.8 x 16.0 (19.0) x 17.5   1.2   45334
Pitch = 22.5 ± 0.4 mm; dt = 0.80 ± 0.08 mm
 0.39     5.0 x 17.0 (20.0) x 26.0   1.8   45394
 0.47     5.5 x 17.5 (20.5) x 26.0   2.2   45474
 0.56     6.0 x 18.0 (21.0) x 26.0   2.5   45564
 0.68     6.6 x 18.5 (21.5) x 26.0   2.8   45684
 0.82     7.2 x 19.0 (22.0) x 26.0   3.2   45824
  1.0     8.0 x 20.0 (23.0) x 26.0   3.8   45105
Pitch = 27.5 ± 0.4 mm; dt = 0.80 ± 0.08 mm
  1.2     8.0 x 21.0 (23.0) x 30.0   4.1   45125
  1.5     9.0 x 22.0 (25.0) x 30.0   4.8   45155
  1.8     10.0 x 23.0 (26.0) x 30.0  5.5   45185
  2.2     11.0 x 24.0 (27.0) x 30.0  6.2   45225
" ],
	[ 400, "
Pitch = 10.0 ± 0.4 mm; dt = 0.60 ± 0.06 mm
          4.5 x 13.5 (15.5) x 12.5   0.5
0.0010                                     55102
0.0012                                     55122
0.0015                                     55152
0.0018                                     55182
0.0022    4.0 x 13.0 (15.5) x 12.5   0.5   55222
0.0027    4.3 x 13.3 (15.5) x 12.5   0.5   55272
0.0033    4.6 x 13.6 (15.5) x 12.5   0.5   55332
0.0039    4.0 x 13.0 (15.5) x 12.5   0.5   55392
0.0047    4.1 x 13.2 (15.5) x 12.5   0.5   55472
          4.6 x 13.6 (15.5) x 12.5   0.5
0.0056                                     55562
0.0068                                     55682
0.0082                                     55822
 0.010                                     55103
 0.012    4.0 x 13.0 (15.5) x 12.5   0.5   55123
 0.015    4.1 x 13.0 (15.5) x 12.5   0.5   55153
 0.018    4.4 x 13.0 (15.5) x 12.5   0.5   55183
 0.022    4.2 x 12.9 (15.5) x 12.5   0.5   55223
 0.027    4.2 x 13.2 (15.5) x 12.5   0.5   55273
 0.033    4.6 x 13.7 (15.5) x 12.5   0.5   55333
Pitch = 15.0 ± 0.4 mm; dt = 0.80 ± 0.08 mm
0.039     5.0 x 13.9 (16.5) x 17.5   0.6   55393
0.047     5.4 x 14.5 (17.0) x 17.5   0.7   55473
0.056     5.0 x 13.7 (16.5) x 17.5   0.6   55563
0.068     5.0 x 13.5 (16.5) x 17.5   0.6   55683
0.082     4.8 x 14.0 (16.5) x 17.5   0.6   55823
 0.10     5.3 x 14.5 (17.5) x 17.5   0.7   55104
 0.12     5.7 x 15.0 (18.0) x 17.5   0.9   55124
 0.15     6.4 x 15.5 (18.5) x 17.5   1.0   55154
Pitch = 22.5 ± 0.4 mm; dt = 0.80 ± 0.08 mm
 0.18     5.6 x 17.5 (20.5) x 26.0   2.2   55184
 0.22     6.3 x 18.5 (21.5) x 26.0   2.8   55224
 0.27     6.0 x 18.0 (21.0) x 26.0   2.5   55274
 0.33     6.4 x 18.5 (21.5) x 26.0   2.8   55334
 0.39     7.1 x 19.0 (21.5) x 26.0   2.8   55394
 0.47     8.0 x 20.0 (22.5) x 26.0   3.8   55474
Pitch = 27.5 ± 0.4 mm; dt = 0.80 ± 0.08 mm
 0.56     7.5 x 20.5 (22.5) x 30.0   3.8   55564
 0.68     8.5 x 21.5 (23.5) x 30.0   4.5   55684
 0.82     9.5 x 22.5 (24.5) x 30.0   5.2   55824
  1.0     10.5 x 23.5 (26.5) x 30.0  5.8   55105
" ],
	[ 630, "
Pitch = 10.0 ± 0.4 mm; dt = 0.60 ± 0.06 mm
0.010     4.3 x 13.1 (15.5) x 12.5   0.5   65103
0.012     4.6 x 13.4 (16.0) x 12.5   0.5   65123
0.015     4.9 x 13.9 (16.5) x 12.5   0.6   65153
0.018     5.3 x 14.3 (17.0) x 12.5   0.6   65183
0.022     5.9 x 14.9 (17.5) x 12.5   0.8   65223
Pitch = 15.0 ± 0.4 mm; dt = 0.80 ± 0.08 mm
0.027     5.5 x 14.5 (17.5) x 17.5   0.7   65273
0.033     6.0 x 15.0 (18.0) x 17.5   0.9   65333
0.039     6.3 x 15.5 (18.5) x 17.5   1.0   65393
0.047     7.0 x 16.0 (19.0) x 17.5   1.2   65473
0.056     7.5 x 16.5 (19.5) x 17.5   1.3   65563
0.068     8.0 x 17.0 (20.0) x 17.5   1.4   65683
Pitch = 22.5 ± 0.4 mm; dt = 0.80 ± 0.08 mm
0.082     6.1 x 18.0 (21.0) x 26.0   2.5   65823
 0.10     7.0 x 19.0 (22.0) x 26.0   3.2   65104
 0.12     7.2 x 19.5 (22.5) x 26.0   3.5   65124
 0.15     8.0 x 21.0 (23.0) x 26.0   3.8   65154
 0.18     9.0 x 22.0 (24.0) x 26.0   4.5   65184
 0.22     10.0 x 23.0 (25.0) x 26.0  5.2   65224
Pitch = 27.5 ± 0.4 mm; dt = 0.80 ± 0.08 mm
 0.27    10.0 x 23.0 (25.0) x 30.0   5.5   65274
 0.33    11.5 x 24.5 (26.5) x 30.0   6.5   65334
 0.39    12.5 x 25.5 (28.5) x 30.0   7.1   65394
 0.47    14.0 x 27.0 (30.0) x 30.0   8.2   65474
" ],
    );
    for my $r (@tbl) {
	my $volt = $$r[0];
	my $tbl = $$r[1];
	#print "volt $volt\n";
	parse_vishay_mkt368($volt, $tbl);
    }
}
#gen_vishay_mkt368();

sub gen_vishay_hvcc() {
    my $doc  = "# http://www.farnell.com/datasheets/2720438.pdf" .
	"# https://www.vishay.com/docs/23144/hvccseries.pdf\n";
    my @data = (
	# from https://www.vishay.com/docs/23144/hvccseries.pdf p.2
	# 10kV
	[  100,  8,  9.0,  5.3, "HVCC103Y6P101" ],
	[  150,  8,  8.0,  4.5, "HVCC103Y6P151" ],
	[  220,  9,  8.0,  4.5, "HVCC103Y6P221" ],
	[  330, 10,  7.5,  4.3, "HVCC103Y6P331" ],
	[  470, 12,  7.5,  4.3, "HVCC103Y6P471" ],
	[  680, 13,  7.5,  3.8, "HVCC103Y6P681" ],
	[ 1000, 15,  7.5,  3.8, "HVCC103Y6P102" ],
	[ 1500, 17,  7.5,  3.8, "HVCC103Y6P152" ],
	[ 2000, 19,  7.5,  3.8, "HVCC103Y6P202" ],
	# 15kV
	[  100,  8,  9.0,  5.3, "HVCC153Y6P101" ],
	[  150,  8,  8.0,  4.5, "HVCC153Y6P151" ],
	[  220,  9,  8.0,  4.5, "HVCC153Y6P221" ],
	[  330, 10,  8.0,  4.3, "HVCC153Y6P331" ],
	[  470, 12,  8.0,  4.3, "HVCC153Y6P471" ],
	[  680, 13,  8.0,  4.3, "HVCC153Y6P681" ],
	[ 1000, 15,  8.0,  4.3, "HVCC153Y6P102" ],
	[ 1500, 19,  8.0,  4.3, "HVCC153Y6P152" ],
	[ 2000, 19,  8.0,  4.3, "HVCC153Y6P202" ],
	# 20kV
	[  100,  8,  9.0,  5.3, "HVCC203Y6P101" ],
	[  150,  8,  8.5,  4.5, "HVCC203Y6P151" ],
	[  220,  9,  8.5,  5.0, "HVCC203Y6P221" ],
	[  330, 12,  8.5,  5.1, "HVCC203Y6P331" ],
	[  470, 13,  8.5,  5.1, "HVCC203Y6P471" ],
	[  680, 15,  8.5,  5.1, "HVCC203Y6P681" ],
	[ 1000, 17,  8.5,  5.1, "HVCC203Y6P102" ],
    );
    my @lead_type = ( # skip short lead "xB" version
	# from http://www.farnell.com/datasheets/2720438.pdf p.3
	# "inline is probably form 6, p.11, in geninfocdiscrfisafe.pdf
	[ "AA", "Straight",  9.5,  0.8 ],
	[ "BA", "Inline",    9.5,  0.8 ],
	[ "CA", "Straight",  9.5,  0.6 ],
	[ "DA", "Inline",    9.5,  0.6 ],
	[ "EA", "Straight", 12.5,  0.8 ],
	[ "FA", "Inline",   12.5,  0.8 ],
	[ "GA", "Straight", 12.5,  0.6 ],
	[ "HA", "Inline",   12.5,  0.6 ],
    );

    $round_first_pin = 1;
    for my $dr (@data) {
	my ($C, $dia, $th, $w, $ocode) = @$dr;
	for my $lr (@lead_type) {
	    my ($lcode, $type, $spacing, $lead) = @$lr;
	    my $name = "${ocode}x${lcode}x";
	    my $px = round(triangle_x($spacing, $w)/2, 0.1);
	    my $py = 0;
	    if ($type ne "Inline") { $py = $w/2; }
	    #my $body = [ $dia, $th - 2*$lead ];
	    # I have to geuss about the body width
	    my $cth = ($th - ($w + $lead))/2; # coating thickness varies from 1.2 to 1.7mm
	    my $body = [ $dia, $w - $lead + $cth/2 ];
	    #printf "%s %5.2f %5.2f %6.1f %4.1f %4.1f %5.2f\n", $name, $px, $py, $th, $w, $lead, $cth;
	    my $drill = lead_to_drill($lead);
	    my @th    = drill2thickness($drill);
	    for (my $ix = 0; $ix < @th; $ix++) {
		my $file = sprintf("%s_%s.fp", $name, thickness_suffix($ix));
		my $th   = $th[$ix];

		element_start($file, $doc);
		pin( -$px, +$py, $drill, $th, "");
		pin( +$px, -$py, $drill, $th, "");
		my @bbw = bb_enlarge($silk_w/2,@bounding_box);
		silk_crect( [0,0], $body, $$body[1]/4, \@bbw);
		element_stop();
	    }
	}
    }
    $round_first_pin = 0;
}
#gen_vishay_hvcc();

sub gen_jedec_do_sm() {
    # surface mount jedec diode outlines
    my @data = (
	# var     A    A1    A2    A3    b     b1    c     c1    D     E     E1    E2    L     R1    R2
	[ 214, "DO-214D.PDF" ], # sma smb smc ..
	[ "AA", 2.30, 2.15, 0.15, 0.17, 2.07, 2.05, 0.28, 0.23, 3.60, 5.40, 4.30, 1.90, 1.15, 0.15, 0.15 ],
	[ "AB", 2.30, 2.15, 0.15, 0.17, 3.05, 3.00, 0.28, 0.23, 5.90, 7.95, 6.85, 4.55, 1.15, 0.15, 0.15 ],
	[ "AC", 2.40, 2.30, 0.15, 0.17, 1.45, 1.40, 0.28, 0.23, 2.60, 5.20, 4.30, 1.65, 1.15, 0.15, 0.15 ],
	[ "AD", 2.95, 2.80, 0.15, 0.17, 1.35, 1.30, 0.28, 0.23, 2.60, 5.25, 4.45, 1.90, 1.15, 0.15, 0.15 ],

	[ 215, "DO-215D.PDF" ], # gull wing
	[ "AA", 2.30, 2.15, 0.15, 0.51, 2.07, 2.05, 0.28, 0.23, 3.60, 6.20, 4.30, 1.90, 0.60, 0.15, 0.15 ],
	[ "AB", 2.30, 2.15, 0.15, 0.51, 3.05, 3.00, 0.28, 0.23, 5.90, 9.90, 6.85, 4.55, 0.80, 0.15, 0.15 ],
	[ "AC", 2.40, 2.30, 0.15, 0.51, 1.45, 1.40, 0.28, 0.23, 2.60, 6.10, 4.30, 1.65, 0.60, 0.15, 0.15 ],
	[ "BA", 2.95, 2.80, 0.15, 0.51, 1.35, 1.30, 0.28, 0.23, 2.60, 6.20, 4.45, 1.90, 0.60, 0.15, 0.15 ],
	[ "AD", 1.20, 1.10, 0.10, 0.00, 0.57, 0.55, 0.10, 0.12, 1.55, 3.70, 2.70, 0.00, 0.25, 0.10, 0.10 ],

	[ 216, "Do-216a.pdf" ], # gullwing - flat pad
	# var    A     A1    b     b1    b2    b3    c     c1    D     E     H     L     L2    L3    R1    R2
	[ "AA", 1.00, 0.10, 0.52, 0.50, 0.85, 0.85, 0.17, 0.15, 1.90, 1.90, 3.75, 0.63, 1.35, 0.50, 0.07, 0.07 ],

	[ "DO-218C.pdf" ], # J-leaad + pad under body
	# var    A     A1     A2   A3    A4    A5    b     b1    c     c1     D     D1     D2    E      E1     H     L     L1    R1    R2
	[ "AA", 5.20, 5.00, 3.95, 2.00, 3.10, 1.05, 2.65, 2.60, 0.67, 0.60, 13.50, 9.00, 10.00, 8.50,  9.75, 15.50, 2.00, 1.00, 0.50, 0.50 ],
	[ "AB", 5.20, 5.00, 3.95, 2.00, 3.00, 0.60, 2.65, 2.60, 0.67, 0.60, 13.50, 9.00, 10.00, 8.50, 10.00, 15.50, 2.00, 1.00, 0.50, 0.50 ],
	[ "AC", 5.20, 5.00, 4.30, 2.00, 3.00, 0.42, 2.65, 2.60, 0.67, 0.60, 13.50, 9.00, 10.00, 8.50, 10.00, 15.50, 2.00, 1.00, 0.50, 0.50 ],

	[ 219, "DO-219.pdf" ], # flat ext. pads
	# var    A     A1    b     b1    b2    b3    c     c1    D     E     H     L     L1
	[ "AA", 1.30, 0.05, 1.07, 1.00, $u  , $u  , 0.20, 0.17, 2.80, 1.80, 3.70, 0.81, $u   ],
	[ "AB", 0.98, 0.05, 1.07, 1.00, $u  , $u  , 0.17, 0.15, 2.80, 1.80, 3.70, 0.60, $u   ],
	[ "AC", 0.60, 0.05, 0.62, 0.60, $u  , $u  , 0.17, 0.15, 1.90, 1.30, 2.50, 0.50, $u   ],
	[ "AD", 0.65, 0.05, 0.62, 0.60, 0.85, 0.82, 0.17, 0.15, 2.20, 1.30, 2.50, 0.65, 1.30 ],

	[ 220, "DO-220B.pdf" ], # flat pads
	# var    A     b     b1    b2    b3    c     c1     D    E     E1    E2    L     L1    L2    F     R
	[ "AA", 0.76, 0.76, 1.20, 1.20, 0.22, 0.20, 0.20, 2.03, 3.85, 3.40, 2.40, 0.60, 0.15, 0.30, 0.30, 0.10 ],

	[ 221, "DO-221A.pdf" ], # flat ext. pads,
	# var    A     b     b1    b2    c     c1    D     E     E1     L     L1    L2
	[ "AA", 1.00, 2.07, 2.05, $u  , 0.28, 0.20, 3.75,  5.50, 4.30, 1.00, 0.00, $u   ],
	[ "AB", 1.00, 3.07, 3.00, $u  , 0.28, 0.20, 5.65,  7.90, 6.70, 1.15, 0.00, $u   ],
	[ "AC", 1.00, 1.45, 1.50, $u  , 0.28, 0.20, 2.80,  5.20, 4.15, 1.00, 0.00, $u   ],
	[ "BA", 1.00, 2.07, 2.05, 2.85, 0.28, 0.20, 3.75,  5.50, 4.30, 1.00, 0.00, 3.20 ],
	[ "BB", 1.00, 3.07, 3.00, 4.65, 0.28, 0.20, 5.65,  7.90, 6.70, 1.15, 0.00, 5.55 ],
	[ "BC", 1.00, 1.45, 1.50, 1.90, 0.28, 0.20, 2.80,  5.20, 4.15, 1.00, 0.00, 2.70 ],

	[ 222, "DO-222A.pdf" ], # flat ext. pads, assymetric
	# var    A     b     b1    b2    b3    c     c1    D     E     E1    h     L     L1    L2    L3    r1    r2
	[ "AA", 0.85, 0.52, 0.55, 0.85, 0.85, 0.07, 0.15, 1.90, 3.80, 2.95, 0.45, 0.55, 2.40, 0.60, 0.35, 0.15. 0.1 ],


    );
    my $nr = 0;
    my $pdf = "";
    my $name = "";
    for my $r (@data) {
	if (@$r == 2) {
	    my ($nr, $pdf) = @$r;
	    $name = "\U$pdf";
	    $name =~ s/\.pdf//i;
	    print "$pdf, $name\n";
	} else {
	    my ($var, $A, $A1, $A2, $A3, $A4, $A5, $b, $b1, $b2, $b3, $c, $c1, $D, $D1, $D2,
		$E, $E1, $E2, $F, $H, $h, $L, $L1, $L2, $L3, $R, $R1, $R2, $r1, $r2) = (undef)x31;
	    my $body;

	    if      ($nr == 214) {
		($var, $A, $A1, $A2, $A3, $b, $b1, $c, $c1, $D, $E, $E1, $E2, $L, $R1, $R2) = @$r;
	    } elsif ($nr == 215) {
		($var, $A, $A1, $A2, $A3, $b, $b1, $c, $c1, $D, $E, $E1, $E2, $L, $R1, $R2) = @$r;
	    } elsif ($nr == 216) {
		($var, $A, $A1, $b, $b1, $b2, $b3, $c, $c1, $D, $E, $H, $L, $L2, $L3, $R1, $R2) = @$r;
	    } elsif ($nr == 218) {
		($var, $A, $A1, $A2, $A3, $A4, $A5, $b, $b1, $c, $c1, $D, $D1, $D2, $E, $E1, $H, $L, $L1, $R1, $R2) = @$r;
	    } elsif ($nr == 219) {
		($var, $A, $A1, $b, $b1, $b2, $b3, $c, $c1, $D, $E, $H, $L, $L1) = @$r;
	    } elsif ($nr == 220) {
		($var, $A, $b, $b1, $b2, $b3, $c, $c1, $D, $E, $E1, $E2, $L, $L1, $L2, $F, $R) = @$r;
	    } elsif ($nr == 221) {
		($var, $A, $b, $b1, $b2, $c, $c1, $D, $E, $E1, $L, $L1, $L2) = @$r;
	    } elsif ($nr == 222) {
		($var, $A, $b, $b1, $b2, $b3, $c, $c1, $D, $E, $E1, $h, $L, $L1, $L2, $L3, $r1, $r2) = @$r;
	    }
	    $body = [ $D, $E ];
	    # TODO
	}
    }
}
#gen_jedec_do_sm();

sub gen_to92() {
    my $doc =
"# https://web.archive.org/web/20170618095849/https://www.jedec.org/sites/default/files/docs/archive/to/to-092.pdf
# https://www.bourns.com/pdfs/TO-92pkg.pdf
# https://en.wikipedia.org/wiki/TO92
# http://d-nb.info/1007763094/34
#
# Filename legend: to93ptdc.fp where
# p = pitch n (narrow 1.27mm), r (1.5mm), s {2.0mm), t (2.5mm), w (wide 2.54mm), x (3.0mm)
#     the r s t x are for manually bent pins for thoose who need it
# t = l (in-line) s (staggered, middle pin bent towards round side) r (reverse staggered)
# d = pin dia * 10, ... 6 (0.6mm) 7 (0.7) 8 (0.8), ...
# c = cu diameter variant
";
    my $name = "to92";
    my $dia = 5;
    my $flat = 4;

    # pins always in 1 2 3 order, left to right when viewing flat side
    my %pitch = ( "n" => 1.27, "r" => 1.5, "s" => 2, "t" => 2.5, "w" => 2.54, "x" => 3.0 );
    my %stagg = ( "l" => 0, "s" => 1, "r" => -1);
    my @pin_dia = ( 4, 5, 6, 7, 8 ); # jedec says 0.407 to 0.533 mm
    #my %n_dia = (6 => 1.3, 7 => 1.4, 8 => 1.5); # cu_dia for narrow pitch

    $round_first_pin = 1;
    for my $pn (sort { $pitch{$a} <=> $pitch{$b} } keys %pitch) {
	my $P = $pitch{$pn};
	for my $sn (sort keys %stagg) {
	    my $S = $stagg{$sn};
	    my $spacing = $P;
	    if ($S) { $spacing *= $s2; }
	    for my $dn (@pin_dia) {
		my $lead_dia = $dn / 10;
		my $drill = lead_to_drill($lead_dia);
		my @thickness = drill2thickness($drill);
		for (my $ix = 0; $ix < @thickness; $ix++) {
		    my $ts = thickness_suffix($ix);
		    my $file = "${name}_$pn$sn$dn$ts.fp";
		    if ($spacing < $thickness[$ix] + $mask_gap) { next; }

		    element_start($file, $doc);
		    silk_circle_flat([0,0], $dia/2, $flat - $dia/2, 0);
		    pin( 0      , -$P, $drill, $thickness[$ix], "");
		    pin( $S * $P,   0, $drill, $thickness[$ix], "");
		    pin( 0      ,  $P, $drill, $thickness[$ix], "");
		    element_stop();
		}
	    }
	}
    }
    $round_first_pin = 0;
}
#gen_to92();

sub gen_to220() {
    my $doc =
"# http://www.jedec.org JEP95 TO-220K.pdf To-220j.pdf
# http://www.national.com/ds/LM/LM2676.pdf
";
    my $name = "to220";
    my @data = (
	# Note: N, the tab is a "pin" in the count of N
      #  var, N,   A, A1,  A2,  A3,  b, b1, b2, b3,  c, c1,   D,  D1,  D2,   E,  E1, E2,   e,  e1,  H1,   L,  L1, L2,   P,  Q
      #[ "AA", ],
      [ "AB", 4, 165, 36,  96,   0, 27, 26, 57, 56, 19, 18, 605, 343, 494, 400, 310, 30, 100, 200, 250, 540, 250,  0, 150,115],
      [ "AC", 3, 165, 36,  96,   0, 27, 26, 57, 56, 19, 18, 605, 343, 494, 400, 310, 30, 100, 200, 250, 540, 250, 70, 150,110],
[ "ns_ta07b", 8, 180, 50, 113, 200, 30, 28, 30, 28, 15, 14, 450, 342, 508, 400, 260, 30,  50, 300, 285, 508, 213,  0, 151,108],
    );
    for my $r (@data) {
	my $var = shift @$r;
	my $N   = shift @$r;
	my ($A, $A1, $A2, $A3, $b, $b1, $b2, $b3, $c, $c1, $D, $D1, $D2,
	    $E, $E1, $E2, $e, $e1, $H1, $L, $L1, $L2, $P, $Q) =  map { mil_to_mm($_) } @$r;

	my $body = [$E,$A];
	my $spacing = $e;
	if ($A3) {
	    $spacing = 2*$e;
	    my $tr = triangle_r($e, $A3);
	    if ($spacing > $tr) { $spacing = $tr; }
	}
	my $pin_dia = triangle_r($c, $b);
	my $drill = lead_to_drill($pin_dia);
	my @thickness = drill2thickness($drill);

	for (my $tx = 0; $tx < @thickness; $tx++) {
	    my $ts = thickness_suffix($tx);
	    my $file = "${name}_${var}_$ts.fp";
	    if ($spacing < $thickness[$tx] + $mask_gap) {
		next;
	    }

	    # standing up TO-220, center is body center
	    element_start($file, $doc);
	    my $n = $N - 1; # don't count the tab
	    my $pitch = $e;
	    if ($n == 2) { $pitch = 2 * $e; }
	    my $xsta = - ($n-1)/2 * $pitch;
	    my $y = $A2 - $A/2;
	    my $y2 = $y + $A3;
	    for (my $ix = 0; $ix < $n; $ix++) {
		my $x = $xsta + $ix * $pitch;
		if ($ix % 2 == 0) { pin($x, $y2, $drill, $thickness[$tx]); }
		else              { pin($x, $y , $drill, $thickness[$tx]); }
	    }
	    my @bbw = bb_enlarge($silk_w/2, @bounding_box);
	    silk_crect([0,0], $body, 0, \@bbw);
	    silk_start(-$E/2, -$A/2 + $A1);
	    silk_rline($E, 0, \@bbw);
	    element_stop();
	}
    }

}
#gen_to220();

sub gen_to263() {
    my $doc =
"# http://www.jedec.org JEP95 TO-263F.pdf
";
    my $name = "jedec_TO-263";
    my $u = undef;
    my @data = (
	# Note: N, the tab is a "pin" in the count of N
	# D1, E1 min, L1, L2 max
	#  var  ,   A,A1,  b, b1, b2, b3,  c, c1, c2,   D,  D1,   E,  E1,   e,   H,  L, L1, L2, L3, N, aaa,
	[ "AA"  , 175, 5, 30, 28, 67, 55, 22, 19, 55, 355, 270, 400, 245, 100, 600, 90, 66, $u, 10, 4, 10 ],
	[ "AA-1", 175, 5, 30, 52, 57, 56, 22, 19, 40, 355, 270, 400, 245, 100, 600, 90, 66, $u, 10, 4, 10 ],
	[ "AB"  , 175, 5, 30, 28, 67, 55, 22, 19, 55, 355, 270, 400, 245, 100, 600, 90, 66, 70, 10, 3, 10 ],
	[ "AB-1", 175, 5, 30, 52, 57, 56, 22, 19, 40, 355, 270, 400, 245, 100, 600, 90, 66, $u, 10, 3, 10 ],
	[ "AC"  ,  65, 5, 55, 52, $u, $u, 18, 15, $u, 345, 250, 395, 315, 100, 495, 60, 50, 40, 10, 3, 10 ],
	[ "BA"  , 175, 5, 30, 52, $u, $u, 22, 19, 55, 355, 270, 400, 245,  67, 600, 90, 66, $u, 10, 6, 10 ],
	[ "BA-1", 175, 5, 30, 52, $u, $u, 22, 19, 40, 355, 270, 400, 245,  67, 600, 90, 66, $u, 10, 6, 10 ],
	[ "BB"  , 175, 5, 30, 52, $u, $u, 22, 19, 55, 355, 270, 400, 245,  50, 600, 90, 66, 70, 10, 5, 10 ],
	[ "BB-1", 175, 5, 30, 52, $u, $u, 26, 19, 55, 355, 270, 400, 245,  67, 600, 90, 66, 70, 10, 5, 10 ],
	[ "CA"  , 175, 5, 28, 52, $u, $u, 22, 19, 55, 355, 270, 400, 245,  50, 600, 90, 66, $u, 10, 8, 10 ],
	[ "CB"  , 175, 5, 28, 52, $u, $u, 26, 19, 55, 355, 270, 400, 245,  50, 600, 90, 66, 70, 10, 7, 10 ],
    );
    for my $r (@data) {
	my $var = shift @$r;
	my $aaa = pop @$r;
	my $N   = pop @$r;
	my ($A, $A1, $b, $b1, $b2, $b3, $c, $c1, $c2, $D, $D1, $E, $E1, $e, $H, $L, $L1, $L2, $L3) =
	    map { mil_to_mm($_) } @$r;
	# body center is origo
	my $body = [$E,$D];
	my $pin = [ $e, $b, $L ];
	my $ext_y = ($H - $L1 - $D/2);
	my $pnum = undef;

	my $cr = 0;

	if ( ($N % 2) == 1) {
	    # missing a pad
	    $pnum = [ (1 .. $N) ];
	    if ($N == 7) {
		$$pnum[5] = undef;
	    } else {
		$$pnum[int($N/2)] = undef;
	    }
	    $N++;
	}
	#print "var / N = $var / $N\n";
	#print Dumper($pnum);

	### iterate over ipc level and corner radius
	my $ipc_size_type = "S";
	if ($e >= 0.625) {
	    $ipc_size_type = "L";
	}
	my @ipc_arr = @{$ipc{$ipc_size_type}};

	for (my $px = 1; $px < @ipc_arr; $px++) {
	    my $suffix = $ipc_hdr[$px];
	    my ($toe, $heel, $side, $roundoff, $courtyard) = @{$ipc_arr[$px]};
	    #print "$toe, $heel, $side, $roundoff, $courtyard\n";
	    my $pad_len = round($$pin[2] + $toe + $heel, $roundoff);
	    my $pad_wid = round($$pin[1] + 2*$side     , $roundoff);
	    my $pad_y  = round($ext_y + $toe - $pad_len/2, $roundoff);
	    my $pad_top = $pad_y - $pad_len/2;
	    my @cthermal = ( 0, -$L1/2 );
	    my @sthermal = ( 1.1*$E, 1.1*($D+$L1) );

	    # 0.95 is to make sure there is no thin sliver of cu
	    my $dist =  $pad_top - ( $cthermal[1] + $sthermal[1]/2 + 0.95*$clearance );
	    #print "var / dist: $var / $dist\n";
	    if ($dist < 0) {
		$sthermal[1] -= -$dist;
		$cthermal[1] -= -$dist/2;
	    }

	    for my $cr ((0, ipc_corner($pad_wid))) {
		my $pad = [ $e, $pad_wid, $pad_len, $cr ];
		my $file;
		if ($cr) {
		    $file = sprintf("%s_%s%sr.fp", $name, $var, $suffix);
		} else {
		    $file = sprintf("%s_%s%s.fp", $name, $var, $suffix);
		}

		element_start($file, $doc);
		pr("#\n");
		pkg_rect_pads([ 0, $N-1, 0, 0], [ $pad_y, $pad_y ], $pad, $pnum, undef);

		pr("# Thermal pad\n");
		pad( $cthermal[0], $cthermal[1], $sthermal[0], $sthermal[1], undef, "", 0, 0);
		#pkg_thermal_pad($$thermal[0], $$thermal[1], $$thermal[2]);

		# body, well, the thermal pad covers the whole body
		#pkg_body_rect($body);
		bb_blcorner($bounding_box[0]);

		element_stop();
	    }
	}

    }

}
#gen_to263();

sub gen_ceramic_th() {
    my $doc = "# old style ceramic with leads
# like e.g. http://www.newark.com/pdfs/datasheets/spc/TA-150.PDF
";

    my $name = "ceramic";
    my @sz = (
	# disc dia, disc thickness, lead spacing, lead dia
	[ 6.0, 2.5, 5.0, 0.8 ],
    );

    for (my $ix = 0; $ix < @sz; $ix++) {
	my $D = $sz[$ix][0]; # disc dia
	my $T = $sz[$ix][1]; # disc thickness
	my $P = $sz[$ix][2]; # lead spacing
	my $d = $sz[$ix][3]; # lead dian

	if ($P <= $d) {
	    warn("$name: spacing <= lead dia / $ix $D $T $P $d");
	    next;
	}
	my $file = sprintf("%s_%02d%02d_%02d%02d.fp", $name, $D*10, $T*10, $P*10, $d*10);
	my $drill = lead_to_drill($d);
	my $cu_dia = drill_to_cudia($drill);

	element_start($file, $doc);
	pin(  0, 0, $drill, $cu_dia, "");
	pin( $P, 0, $drill, $cu_dia, "");

	# disc inclination
	my $alfa = -asin(($d+$T/4)/$P);
	my $body_e = polar_vec([1,$alfa]);
	my $body_vec = vec_mul($D, $body_e);

	my $center = [ $P / 2, 0 ];
	my $body_start = vec_sub( $center, vec_mul( 0.5, $body_vec));
	my $body_end   = vec_add( $body_start, $body_vec);
	my $body_normal = vec_normal($body_e);

	#silk_width(0.12);
	#silk_vstart($body_start);
	#silk_vrline(vec_mul($T/4, $body_normal));
	#silk_vrline($body_vec);
	#silk_vrline(vec_mul(-$T/2, $body_normal));
	#silk_vrline(vec_reverse($body_vec));
	#silk_vrline(vec_mul($T/4, $body_normal));

	my $rr;
	{   # get radius from segment dimensions
	    my $h = $T/4;
	    my $s = $D;
	    $rr = $s*$s / (8*$h) + $h / 2;
	}
	my $arc_center;

	# main body arc's
	my $beta = asin($D/2 / $rr);
	my $angsta = 3/2*$pi - $beta - $alfa;
	my $sweep = rad_deg(2*$beta);

	$arc_center = vec_add( $center, vec_mul($rr-$T/2, $body_normal));
	silk_arc($arc_center, $rr, rad_deg($angsta), $sweep);

	$arc_center = vec_add( $center, vec_mul(-($rr-$T/2), $body_normal));
	silk_arc($arc_center, $rr, 180+rad_deg($angsta), $sweep);

	# end arc's
	my $hh = $T/4 * tan($beta);
	$rr = $T/4  /  cos($beta);
	$angsta = rad_deg($beta - $alfa) - 90;
	$sweep = 2*(90 - rad_deg($beta));

	$arc_center = vec_add( $body_start, vec_mul($hh, $body_e));
	silk_arc($arc_center, $rr, $angsta, $sweep);

	$arc_center = vec_add( $body_end, vec_mul(-$hh, $body_e));
	silk_arc($arc_center, $rr, 180+$angsta, $sweep);

	element_stop();
    }

}
#gen_ceramic_th();

sub gen_trimmer_open() {
    my $doc =
"# old style open (without case) trimmer
";
    my $name = "trimmer_open";
    my $X = 10;
    my $Y = 4;
    my $P = 2.5;
    my $D = 1;
    my $drill = 1.3;
    my $cu_dia = 2.4;

    my $file = "${name}_${X}x$Y.fp";
    $round_first_pin = 1;
    element_start($file, $doc);
    pin( -$P,  0 , $drill, $cu_dia, "");
    pin(  0 , -$P, $drill, $cu_dia, "");
    pin(  $P,  0 , $drill, $cu_dia, "");
    silk_rect([-$X/2, -$P],[$X/2,$Y-$P],0,);
    element_stop();
    $round_first_pin = 0;
}
#gen_trimmer_open();

# pkgr = {
#   pfx => ...
#   doc => ...
#   body_func => ...
#   body_arg  => [ ... ]
#   lead  => {
#     <drill_label> => {
#       lead_sz => [x,y]
#       hole_dia => ...
#       min_sep => ...
#       th => [ thickness... ]
#     }
#   }
#   pin => {
#     <pin_number> => {
#       name => pinname
#       <drill_label> => [ [x,y], ... ], ...
#     }
#   }
# }

sub pkgr_init($) {
    my $pkgr = shift;
    if (!defined($pkgr)) { $pkgr = { }; }
    if (!defined($$pkgr{lead})) { $$pkgr{lead} = {}; }
    if (!defined($$pkgr{pin })) { $$pkgr{pin } = {}; }

    $pkgr;
}
sub pkgr_show($) {
    my $pkgr = shift;

    my $pfx  = $$pkgr{pfx};
    my $desc = $$pkgr{desc};
    my $doc  = $$pkgr{doc};
    my $body_func = $$pkgr{body_func};
    my $body_offs = $$pkgr{body_offset}; # [...]
    my $body_data = $$pkgr{body_data}; # [...]
    my $leadr = $$pkgr{lead};
    my $pinr  = $$pkgr{pin};

    print "pfx:  $pfx\n";
    print "desc: $desc\n";
    print "doc:\n";
    my $str = $doc;
    $str =~ s/\n$//;
    $str =~ s/\n/\n /g;
    print " ", $str, "\n";
    print "body_func: ", defined($body_func) ? "yes\n" : "no\n";
    print "body_offset: [ $$body_offs[0], $$body_offs[1] ]\n";
    print "body_data: [";
    for my $item (@$body_data) {
	my $type = ref($item);
	if ($type eq "ARRAY") {
	    print " [ ", join(", ", @$item), " ],",
	} elsif ($type eq "") {
	    print " ", $item, ",";
	} else {
	    print "unknown type $type\n";
	}
    }
    print " ]\n";

    print "lead:\n";
    for my $k (sort keys %$leadr) {
	my $v = $$leadr{$k};
	my $lead_sz  = $$v{lead_sz} // 0;
	my $hole_dia = $$v{hole_dia} // 0;
	my $min_sep  = $$v{min_sep} // 0;
	my $thr      = $$v{th} // [];
	print "   $k => { lead_sz => [ ", join(", ", @$lead_sz), " ], hole_dia => $hole_dia, min_sep => $min_sep, th => [ ", join(", ", @$thr), " ], }\n";
    }

    my @pinno  = pkgr_pinno($pkgr);
    my @pintxt = pkgr_pintxt($pkgr);

    for my $pinno (@pinno, @pintxt) {
	my $rr = $$pkgr{pin}{$pinno};
	my $name = $$rr{name} // "undef";
	print "$pinno $name:\n";
	for my $drill (sort grep { $_ ne "name" } keys %$rr) {
	    my $xy = $$rr{$drill};
	    print "  $drill: ";
	    for my $xy (@$xy) {
		my ($x, $y) = @$xy;
		print " [ $x, $y ]";
	    }
	    print "\n";
	}
	print "\n";
    }
}
sub pkgr_pinno($) {
    my $pkgr  = shift;
    my @pinno = ();
    if (defined($pkgr) && defined($$pkgr{pin})) {
	@pinno  = sort { $a <=> $b } grep { m/^\d+/ } keys %{$$pkgr{pin}};
    }
    @pinno;
}
sub pkgr_pintxt($) {
    my $pkgr  = shift;
    my @pintxt = ();
    if (defined($pkgr) && defined($$pkgr{pin})) {
	@pintxt  = sort { $a cmp $b } grep { !m/^\d+/ } keys %{$$pkgr{pin}};
    }
    @pintxt;
}
sub pkgr_add($$$$@) {
    my $pkgr  = shift;
    my $pinno = shift;
    my $name  = shift;
    my $drill_label = shift;
    my @xy    = @_;

    $pkgr = pkgr_init($pkgr);
    if (!defined($$pkgr{pin}{$pinno})) { $$pkgr{pin}{$pinno} = {}; }
    my $current = $$pkgr{pin}{$pinno};
    if (defined($name)) {
	if (defined($$current{name})) {
	    if ($$current{name} eq $name) {
		# ok do nothing
	    } else {
		warn("name mismatch for pin $pinno: <$$current{name}> neq <$name>");
	    }
	} else {
	    $$current{name} = $name;
	}
    } else {
	# do nothing
    }
    if (!defined($$current{$drill_label})) { $$current{$drill_label} = [] };
    push @{$$current{$drill_label}}, @xy;

    $pkgr;
}
sub pkgr_extract_common_body(@) {
    my ($body_f, $body_data);
    my @pkgr = ();

    for (my $bx = 0; $bx < @_; $bx++) {
	my $br = $_[$bx]; # [ <opt. bofy func>, <body func data>, the rest... ]

	my $px;
	if (ref($$br[0]) eq "CODE") {
	    $body_f = $$br[0];
	    $body_data = $$br[1];
	    $px = 2;
	} else {
	    $body_f = \&silk_crectr;
	    $body_data = $$br[0];
	    $px = 1;
	}
	for (; $px < @$br; $px++) {
	    my $pinarr = $$br[$px];

	    my $leaddata    = $$pinarr[0];
	    my $pindata     = $$pinarr[1];
	    for (my $fx = 2; $fx < @$pinarr; $fx++) {
		my $fp_data = $$pinarr[$fx];
		my ($pfx, $desc, $doc, $pinname, $body_offset) = @$fp_data;
		my @data = ($pfx, $desc, $doc, $pinname, $body_f, $body_offset, $body_data, $leaddata, $pindata);
		push @pkgr, pkgr_extract_data(\@data);
	    }
	}
    }
    @pkgr;
}
sub pkgr_extract_data($) {
    my $data = shift;
    my $pkgr = {};

    my ($pfx, $desc, $doc, $pinname, $body_f, $body_offset, $body_data, $lead, $pos) = @$data;

    $$pkgr{pfx}  = $pfx;
    $$pkgr{desc} = $desc;
    $$pkgr{doc}  = $doc;
    $$pkgr{body_func} = $body_f;
    $$pkgr{body_offset} = $body_offset;
    $$pkgr{body_data} = $body_data;
    $$pkgr{lead} = {};

    for my $k (keys %$lead) {
	my $v = $$lead{$k};
	my ($x, $y, $hole, $min_sep) = @$v;
	my $lead_dia = $x;
	my @thickness;
	if (ref($hole) eq 'ARRAY') {
	    @thickness = @$hole;
	    $hole = shift @thickness;
	    if (!defined($hole) || $hole == 0) {
		$hole = lead_to_drill($x, $y);
	    }
	} else {
	    if (!defined($hole) || $hole == 0) {
		$hole = lead_to_drill($x, $y);
	    }
	    @thickness = drill2thickness($hole);
	}
	my $max_th = $min_sep - $mask_gap;
	push @thickness, $max_th;
	for (my $tx = 0; $tx < @thickness; $tx++) {
	    if ($thickness[$tx] > $max_th) { $thickness[$tx] = 0; }
	}
	$$pkgr{lead}{$k} = { lead_sz => [ $x, $y ], hole_dia => $hole, min_sep => $min_sep, th => [ @thickness ] };
    }

    my @pinname = @$pinname;

    $$pkgr{pin} = {};
    my $nxt = 0;
    for my $rr (@$pos) {
	if (ref($rr) eq "ARRAY") {
	    my $topno = $nxt;
	    $nxt += @$rr - 3;
	    my $type = $$rr[0];
	    my $drill = $$rr[1];
	    if ($type eq 'xy') {
		my $x = $$rr[2];
		for (my $rx = 3; $rx < @$rr; $rx++) {
		    my $y = $$rr[$rx];
		    ++$topno;
		    next if (!defined($y));
		    my $name = $pinname[$topno];
		    next unless ($name);
		    pkgr_add($pkgr, $topno, $name, $drill, [ $x, $y ]);
		}
	    } elsif ($type eq 'yx') {
		my $y = $$rr[2];
		for (my $rx = 3; $rx < @$rr; $rx++) {
		    my $x = $$rr[$rx];
		    ++$topno;
		    next if (!defined($x));
		    my $name = $pinname[$topno];
		    next unless ($name);
		    pkgr_add($pkgr, $topno, $name, $drill, [ $x, $y ]);
		}
	    } elsif ($type eq 'ydx') {
		my $y = $$rr[2];
		my $x = 0;
		for (my $rx = 3; $rx < @$rr; $rx++) {
		    my $dx = $$rr[$rx];
		    ++$topno;
		    next if (!defined($dx));
		    my $name = $pinname[$topno];
		    $x += $dx;
		    next unless ($name);
		    pkgr_add($pkgr, $topno, $name, $drill, [ $x, $y ]);
		}
	    } elsif ($type eq 'xdy') {
		my $x = $$rr[2];
		my $y = 0;
		for (my $rx = 3; $rx < @$rr; $rx++) {
		    my $dy = $$rr[$rx];
		    ++$topno;
		    next if (!defined($dy));
		    my $name = $pinname[$topno];
		    $y += $dy;
		    next unless ($name);
		    pkgr_add($pkgr, $topno, $name, $drill, [ $x, $y ]);
		}
	    } else {
		warn("pkgr_merge(): unknown type ($type)");
	    }
	} elsif (ref($rr) eq "HASH") {
	    for my $k (keys %$rr) {
		my $v = $$rr{$k};
		my $name = $$v{name};
		for my $drill (grep { $_ ne "name" } keys %$v) {
		    my $xy = $$v{$drill};
		    pkgr_add($pkgr, $k, $name, $drill, @$xy);
		}
	    }
	}
    }

    $pkgr;
}
sub th_generator(@) {
    my @pkg = @_;

    for my $pkgr (@pkg) {
	my %thickness;

	my $pfx  = $$pkgr{pfx};
	my $desc = $$pkgr{desc};
	my $doc  = $$pkgr{doc};
	my $body_func = $$pkgr{body_func};
	my $body_offs = $$pkgr{body_offset};
	my $body_data = $$pkgr{body_data}; # [...]
	my $leadr = $$pkgr{lead};
	my $pinr  = $$pkgr{pin};

	# has a "1" where thickness grade is valid for all drill sizes
	my @thickness_mask = (1) x @thickness_suffix;
	my $err = "";

	for my $k (keys %$leadr) {
	    my $th = $$leadr{$k}{th};

	    # note where too big thickness would result into a short
	    for (my $it = 0; $it < @$th; $it++) {
		next if (!$thickness_mask[$it]);
		if ($$th[$it] == 0) {
		    $thickness_mask[$it] = 0;
		}
	    }
	}

	my @pinno  = pkgr_pinno($pkgr);
	my @pintxt = pkgr_pintxt($pkgr);

	for (my $it = 0; $it < @thickness_mask; $it++) {
	    next if (!$thickness_mask[$it]);

	    my $file = sprintf("%s_%s.fp", $pfx, thickness_suffix($it));
	    element_start($file, "", $desc, undef, $pfx);
	    attribute("doc", $doc);
	    pr "\n";

	    for my $pinno (@pinno) {
		my $rr = $$pinr{$pinno};
		next if (!defined($rr));
		my $name = $$rr{name};
		my @drill_label = grep { $_ ne "name" } keys %$rr;

		for my $drill_label (@drill_label) {
		    my $hole = $$leadr{$drill_label}{hole_dia};
		    my $th = $$leadr{$drill_label}{th}[$it];
		    my @pos = @{$$rr{$drill_label}};
		    for my $pos (@pos) {
			pin( $$pos[0], $$pos[1], $hole, $th, $name, "", $pinno );
		    }
		}
	    }

	    my @bbw = bb_sort(@bounding_box);
	    @bbw = bb_enlarge($silk_w/2,@bbw);

	    if (defined($body_func)) {
		&$body_func($body_offs, $body_data, \@bbw);
	    } elsif (defined($body_data)) {
		silk_crectr($body_offs, $body_data, \@bbw);
	    } else {
		silk_bb();
	    }
	    element_stop();
	}
	#pkgr_show($pkgr);
    }
}

sub gen_power_th() {
    # @data is a list of pagckes for various dc/dc converters
    # my goal is to make it easy to write down the fp in this
    # format

    # I generally want the fp to be centered on the body,
    # but it is convenitent if pins/pads is on suitable raster points
    # hence the offset.
    # Alignment of the package body and the set of pins seems to vary
    # amongs theese komponents, one the drawings have the measurements
    # relative one pkg.corner, another relative another corner while a
    # third might have them centered on the body, so I'll put the offset
    # together with the most component specific data of the components.

    # regarding the body, I prefer to have the long dimension along the x-axis
    # and pin #1 to the left

    my @data = (
	[
	    [   [ 9.40, 6.00 ], 0 ],
	    [   { "a" => [ 0.64, 0.64, undef, 1.7 ], },
		[[ 'ydx', "a", 0, -2*1.7, (1.7)x4 ]],
		[   "traco_tsr3_pos",
		    "DC/DC Converter",
		    "https://www.tracopower.com/sites/default/files/products/datasheets/tsr3_datasheet.pdf",
		    [ undef, qw| Ctrl +Vin GND +Vout Trim | ],
		    [ 0, 0.7 ],
		], [
		    "traco_tsr3_neg",
		    "DC/DC Converter",
		    "https://www.tracopower.com/sites/default/files/products/datasheets/tsr3_datasheet.pdf",
		    [ undef, qw| Ctrl +Vin -Vout GND Trim | ],
		    [ 0, 0.7 ],
		]
	    ]
	], [
	    [   [ 9.40, 15.5 ], 0 ],
	    [   { "a" => [ 0.64, 0.64, undef, 1.7 ], },
		[[ 'ydx', "a", 0, -2*1.7, (1.7)x4 ]],
		[   "traco_tsr3a_pos",
		    "DC/DC Converter",
		    "https://www.tracopower.com/sites/default/files/products/datasheets/tsr3_datasheet.pdf",
		    [ undef, qw| Ctrl +Vin GND +Vout Trim | ],
		    [ 0, 1.5-15.5/2 ],
		], [
		    "traco_tsr3a_neg",
		    "DC/DC Converter",
		    "https://www.tracopower.com/sites/default/files/products/datasheets/tsr3_datasheet.pdf",
		    [ undef, qw| Ctrl +Vin -Vout GND Trim | ],
		    [ 0, 1.5-15.5/2 ],
		]
	    ]
	], [
	    [   [ 10.00, 6.45 ], 0 ],
	    [   { "a" => [ 0.64, 0.64, undef, 2.54 ], },
		[[ 'ydx', "a", 0, -2.54, (2.54)x2 ]],
		[   "traco_tsr1_5E",
		    "DC/DC Converter",
		    "https://www.tracopower.com/sites/default/files/products/datasheets/tsr1_5e_datasheet.pdf",
		    [ undef, qw| +Vin GND +Vout | ],
		    [ 0, -2.82+3.75-6.45/2 ],
		]
	    ]
	], [
	    [   [ 10.40, 6.00 ], 0 ],
	    [   { "a" => [ 0.64, 0.64, undef, 1.7 ], },
		[[ 'ydx', "a", 0, -2*1.7, (1.7)x4 ]],
		[   "traco_tsr3_24_pos",
		    "DC/DC Converter",
		    "https://www.tracopower.com/sites/default/files/products/datasheets/tsr3_datasheet.pdf",
		    [ undef, qw| Ctrl +Vin GND +Vout Trim | ],
		    [ 0, 0.7 ],
		], [
		    "traco_tsr3_24_neg",
		    "DC/DC Converter",
		    "https://www.tracopower.com/sites/default/files/products/datasheets/tsr3_datasheet.pdf",
		    [ undef, qw| Ctrl +Vin -Vout GND Trim | ],
		    [ 0, 0.7 ],
		]
	    ]
	], [
	    [   [ 10.40, 16.50 ], 0 ],
	    [   { "a" => [ 0.64, 0.64, undef, 1.7 ], },
		[[ 'ydx', "a", 0, -2*1.7, (1.7)x4 ]],
		[   "traco_tsr3a_24_pos",
		    "DC/DC Converter",
		    "https://www.tracopower.com/sites/default/files/products/datasheets/tsr3_datasheet.pdf",
		    [ undef, qw| Ctrl +Vin GND +Vout Trim | ],
		    [ 0, 1.5-16.5/2 ], # TODO: 1.5 is a guess
		], [
		    "traco_tsr3a_24_neg",
		    "DC/DC Converter",
		    "https://www.tracopower.com/sites/default/files/products/datasheets/tsr3_datasheet.pdf",
		    [ undef, qw| Ctrl +Vin -Vout GND Trim | ],
		    [ 0, 1.5-16.5/2 ], # TODO: 1.5 is a guess
		]
	    ]
	], [
	    # body drawing function (optional), args: <offset> other args...
	    [   [ 11.5, 6.1 ], 0 ], #  body func. arguments, omitting first arg, <offset>
	    [ # first pin placement
		{ "a" => [ 0.5, 0.25, undef, 2.54 ], }, # pin sizes
		[[ 'ydx', "a", 0, -1.5*2.54, (2.54)x3 ]], # type, pin_dia_label, y_pos, x1, +dx2, ...
		[ # first footprint
		    "traco_tme", # footprint file name prefix
		    "DC/DC Converter", # description
		    "https://www.tracopower.com/sites/default/files/products/datasheets/tme_datasheet.pdf", # doc
		    [ undef, qw| -Vin +Vin -Vout +Vout | ], # pin number (used as array index) to pin name mapping
		    [ -1.9-1.5*2.54 + 11.5/2, 6.1/2 - 4.2-0.25/2] # offset to apply to body
		]
	    ],
	], [
	    [   [ 11.5, 7.1 ], 0 ], # same as aboe but a little thicker
	    [   { "a" => [ 0.5, 0.25, undef, 2.54 ], },
		[[ 'ydx', "a", 0, -1.5*2.54, (2.54)x3 ]],
		[   "traco_tme_24",
		    "DC/DC Converter",
		    "https://www.tracopower.com/sites/default/files/products/datasheets/tme_datasheet.pdf",
		    [ undef, qw| -Vin +Vin -Vout +Vout | ],
		    [ -1.9-1.5*2.54 + 11.5/2, 7.1/2 - 4.2-0.25/2]
		]
	    ],
	], [
	    [   [ 11.50, 7.55 ], 0 ],
	    [   { "a" => [ 0.7, 0.25, undef, 2.54 ], },
		[[ 'ydx', "a", 0, -2.54, (2.54)x2 ]],
		[   "traco_tsr0_5",
		    "DC/DC Converter",
		    "https://www.tracopower.com/sites/default/files/products/datasheets/tsr0_5_datasheet.pdf",
		    [ undef, qw| +Vin GND +Vout | ],
		    [ 2.54+3.2-11.5/2, 0.25/2+2-7.75/2 ]
		]
	    ]
	], [
	    [   [ 11.60, 7.50 ], 0 ],
	    [   { "a" => [ 0.5, 0.3, undef, 2.54 ], },
		[[ 'ydx', "a", 0, -2.54, (2.54)x2 ]],
		[   "traco_tsr1e",
		    "DC/DC Converter",
		    "https://www.tracopower.com/sites/default/files/products/datasheets/tsr0_5_datasheet.pdf",
		    [ undef, qw| +Vin GND +Vout | ],
		    [ -3.26-2.54+11.6/2, -5.45+7.5/2 ]
		]
	    ]
	], [
	    [ [ 11.68, 6 ], 0 ],
	    [   { "a" => [ 0.5, 0.25, undef, 2.54 ], },
		[[ 'ydx', "a", 0, -1.5*2.54, (2.54)x3 ]],
		[   "traco_tba1",
		    "DC/DC Converter",
		    "https://www.tracopower.com/sites/default/files/products/datasheets/tba1_datasheet.pdf",
		    [ undef, qw| -Vin +Vin -Vout +Vout | ],
		    [ -1.5*2.54-2.03+11.68/2, 1.35-6/2]
		], [
		    "traco_tea1",
		    "DC/DC Converter",
		    "https://www.tracopower.com/sites/default/files/products/datasheets/tea1_datasheet.pdf",
		    [ undef, qw| -Vin +Vin -Vout +Vout | ],
		    [ -1.5*2.54-2.03+11.68/2, 0.90-6/2]
		]
	    ]
	], [
	    [ [ 11.70, 7.50 ], 0 ],
	    [   { "a" => [ 0.5, 0.25, undef, 2.54 ], },
		[[ 'ydx', "a", 0, -2.54, (2.54)x2 ]],
		[   "traco_tsn1",
		    "DC/DC Converter",
		    "https://www.tracopower.com/sites/default/files/products/datasheets/tsn1_datasheet.pdf",
		    [ undef, qw| GND -Vin -Vout  | ],
		    [ -3.3-2.54+11.7/2, 3.1-7.5/2]
		], [
		    "traco_tsr1",
		    "DC/DC Converter",
		    "https://www.tracopower.com/sites/default/files/products/datasheets/tsr1_datasheet.pdf",
		    [ undef, qw| +Vin GND +Vout | ],
		    [ 3.3+2.54-11.7/2, -5.5+7.5/2]
		], [
		    "traco_tsrn1",
		    "DC/DC Converter",
		    "https://www.tracopower.com/sites/default/files/products/datasheets/tsrn1_datasheet.pdf",
		    [ undef, qw| +Vin GND +Vout | ],
		    [ 3.3+2.54-11.7/2, 2.4-7.5/2]
		]
	    ]
	], [
	    [ [ 11.70, 16.50 ], 0 ],
	    [   { "a" => [ 0.5, 0.25, undef, 2.54 ], },
		[[ 'ydx', "a", 0, -2.54, (2.54)x2 ]],
		[   "traco_tsn1a",
		    "DC/DC Converter",
		    "https://www.tracopower.com/sites/default/files/products/datasheets/tsn1_datasheet.pdf",
		    [ undef, qw| GND -Vin -Vout  | ],
		    [ -3.3-2.54+11.7/2, -1.5-16.5/2]
		]
	    ]
	], [
	    [ [ 11.70, 10.20 ], 0 ],
	    [   { "a" => [ 0.5, 0.25, undef, 2.54 ], },
		[[ 'ydx', "a", 0, -2.54, (2.54)x2 ]],
		[
		    "traco_tsrn1a",
		    "DC/DC Converter",
		    "https://www.tracopower.com/sites/default/files/products/datasheets/tsrn1_datasheet.pdf",
		    [ undef, qw| +Vin GND +Vout | ],
		    [ -3.3-2.54+11.7/2, 0.25/2-1.5-10.2/2]
		]
	    ]
	], [
	    [ [ 11.90, 7.70 ], 0 ],
	    [   { "a" => [ 0.5, 0.25, undef, 2.0 ], },
		[[ 'ydx', "a", 0, -4.4, 2, 2.8, (2)x2 ]],
		[
		    "traco_trnN_single",
		    "DC/DC Converter",
		    "https://www.tracopower.com/sites/default/files/products/datasheets/trn1_datasheet.pdf trn3",
		    [ undef, qw| -Vin +Vin +Vout |, undef, "-Vout" ],
		    [ 4.4+1.6-11.9/2, 3.7-7.7/2 ]
		], [
		    "traco_trnN_dual",
		    "DC/DC Converter",
		    "https://www.tracopower.com/sites/default/files/products/datasheets/trn1_datasheet.pdf trn3",
		    [ undef, qw| -Vin +Vin +Vout Common -Vout | ],
		    [ 4.4+1.6-11.9/2, 3.7-7.7/2 ]
		]
	    ]
	], [
	    [ [ 12.00, 8.60 ], 0 ],
	    [   { "a" => [ 0.5, 0.25, undef, 2.54 ], },
		[[ 'ydx', "a", 0, -2.54, (2.54)x2 ]],
		[
		    "traco_tsr0_6wi",
		    "DC/DC Converter",
		    "https://www.tracopower.com/sites/default/files/products/datasheets/tsr0_6wi_datasheet.pdf",
		    [ undef, qw| +Vin GND +Vout | ],
		    [ 3.5+2.54-12.0/2, 5.6-8.6/2]
		]
	    ]
	], [
	    [ [ 12.00, 13.40 ], 0 ],
	    [   { "a" => [ 0.5, 0.25, undef, 2.54 ], },
		[[ 'ydx', "a", 0, -2.54, (2.54)x2 ]],
		[
		    "traco_tsr0_6awi",
		    "DC/DC Converter",
		    "https://www.tracopower.com/sites/default/files/products/datasheets/tsr0_6wi_datasheet.pdf",
		    [ undef, qw| +Vin GND +Vout | ],
		    [ 3.5+2.54-12.0/2, -1.9-13.4/2]
		]
	    ]
	], [
	    [ [ 12.10, 8.60 ], 0 ],
	    [
		{ "a" => [ 0.5, 0.25, undef, 2.54 ],
		  "b" => [ 2.0, 0.6, undef, 3.8 ] },
		[[ 'ydx', "a", 0, -2.54, (2.54)x2 ],
		 [ 'yx' , "b", -1.1, -11.5/2, 11.5/2 ] ],
		[
		    "traco_tsr1wi",
		    "DC/DC Converter",
		    "https://www.tracopower.com/sites/default/files/products/datasheets/tsr1wi_datasheet.pdf",
		    [ undef, qw| +Vin GND +Vout Case Case | ],
		    [ 0, -1.1]
		]
	    ]
	], [
	    [ [ 12.10, 17.50 ], 0 ],
	    [
		{ "a" => [ 0.5, 0.25, undef, 2.54 ],
		  "b" => [ 2.0, 0.4, undef, 6 ] },
		[[ 'ydx', "a", 0, -2.54, (2.54)x2 ],
		 [ 'xy' , "b", 0, -19.6 ] ],
		[
		    "traco_tsr1awi",
		    "DC/DC Converter",
		    "https://www.tracopower.com/sites/default/files/products/datasheets/tsr1wi_datasheet.pdf",
		    [ undef, qw| +Vin GND +Vout Case Case | ],
		    [ 0, -2.4+0.5 -17.5/2 ]
		]
	    ]
	], [ # tdn 1/3/5wism is the same but with pins bent outwards for surface mounting
	    [ [ 13.2, 9.1 ], 0 ],
	    [   { "a" => [ 0.6, 0.25, undef, 2 ], },
	        [[ 'xy', "a", -2.54, 3, 1, -1, -3 ],
	         [ 'xy', "a",  2.54, 3, 1, -1 ]],
		[
		    "traco_tdnNwi_single",
		    "DC/DC Converter",
		    "https://www.tracopower.com/sites/default/files/products/datasheets/tdn1wi_datasheet.pdf tdn3wi tdn5wi",
		    [ undef, "+Vin", "-Vin", undef, "Ctrl", "NC", "-Vout", "+Vout" ],
		    [ 0,0 ]
		], [
		    "traco_tdnNwi_dual",
		    "DC/DC Converter",
		    "https://www.tracopower.com/sites/default/files/products/datasheets/tdn1wi_datasheet.pdf tdn3wi tdn5wi",
		    [ undef, "+Vin", "-Vin", undef, "Ctrl", "-Vout", "Common", "+Vout" ],
		    [ 0,0 ]
		]
	    ],
	], [
	    [ [ 14.00, 7.50 ], 0 ],
	    [
		{ "a" => [ 0.46, 0.46, undef, 2.54 ], },
		[[ 'ydx', "a", 0, -2.54, (2.54)x2 ]],
		[
		    "traco_tsr2wi",
		    "DC/DC Converter",
		    "https://www.tracopower.com/sites/default/files/products/datasheets/tsr2_datasheet.pdf",
		    [ undef, qw| +Vin GND +Vout | ],
		    [ 2.54+4.5-14/2, 3.89 - 7.5/2 ]
		]
	    ]
	], [
	    [ [ 14, 14 ], 0 ],
	    [
		{ "a" => [ 0.5, 0, undef, 2.54 ], },
		[[ "ydx", "a",  7.62/2, -1.5*2.54, (2.54)x3 ],
		 [ 'ydx', "a", -7.62/2, 1.5*2.54, (-2.54)x3 ]],
		[
		    "traco_tdlN_single",
		    "DC/DC Converter",
		    "https://www.tracopower.com/sites/default/files/products/datasheets/tdl2_datasheet.pdf tdl3",
		    [ undef, "-Vin", undef, undef, "+Vin", "+Vout", undef,  "-Vout" ],
		    [ 1.5*2.54+3.19-14/2, 7.62/2+3.19 - 14/2 ],
		], [
		    "traco_tdlN_dual",
		    "DC/DC Converter",
		    "https://www.tracopower.com/sites/default/files/products/datasheets/tdl2_datasheet.pdf tdl3",
		    [ undef, "-Vin", undef, undef, "+Vin", "+Vout", "Common",  "-Vout" ],
		    [ 7.62/2+3.19-14/2, 7.62/2+ 3.19 - 14/2 ],
		]
	    ],
	], [
	    [ [ 17.00, 7.62 ], 0 ],
	    [
		{ "a" => [ 0.5, 0.25, undef, 2.54 ], },
		[[ 'ydx', "a", 0, -2.5*2.54, (2.54)x5 ]],
		[
		    "traco_tmr1_single",
		    "DC/DC Converter",
		    "https://www.tracopower.com/sites/default/files/products/datasheets/tmr1_datasheet.pdf",
		    [ undef, qw| -Vin +Vin |, undef, "+Vout", undef, "-Vout" ],
		    [ -2.5*2.54-2.15+17/2, -2.5 + 7.62/2 ]
		], [
		    "traco_tmr1_dual",
		    "DC/DC Converter",
		    "https://www.tracopower.com/sites/default/files/products/datasheets/tmr1_datasheet.pdf",
		    [ undef, qw| -Vin +Vin |, undef, qw| +Vout Common -Vout | ],
		    [ -2.5*2.54-2.15+17/2, -2.5 + 7.62/2 ]
		]
	    ]
	], [
	    [ [ 12.8, 18.9 ], 0 ],
	    [
		{ "a" => [ 0.8, 0.25, undef, 2.54 ], },
		[ [ 'xdy', "a", -13.55/2, 18.9/2-1.8-5.08-10.16, (2.54)x6 ],
		  [ 'xdy', "a",  13.55/2, 18.9/2-1.8, (-2.54)x6 ]],
		[
		    "traco_tdrN_single",
		    "DC/DC Converter",
		    "https://www.tracopower.com/sites/default/files/products/datasheets/tdr2_datasheet.pdf 2wi 3 and 3wi",
		    [ undef, "-Vin", "Ctrl", (undef)x3, "NC", "NC", "+Vout", "-Vout", (undef)x4, "+Vin" ],
		    [ 0, 0 ]
		], [
		    "traco_tdrN_dual",
		    "DC/DC Converter",
		    "https://www.tracopower.com/sites/default/files/products/datasheets/tdr2_datasheet.pdf 2wi 3 and 3wi",
		    [ undef, "-Vin", "Ctrl", (undef)x3, "Common", "-Vout", "+Vout", "Common", (undef)x4, "+Vin" ],
		    [ 0, 0 ]
		]
	    ]
	], [
	    [ [ 19.5, 6 ], 0 ],
	    [
		{ "a" => [ 0.5, 0.25, undef, 2.54 ], },
		[[ 'ydx', "a", 0, -3*2.54, (2.54)x6 ]],
		[
		    "traco_tba1e_single",
		    "DC/DC Converter",
		    "https://www.tracopower.com/sites/default/files/products/datasheets/tba1e_datasheet.pdf",
		    [ undef, "+Vin", "-Vin", undef, "-Vout", undef,  "+Vout" ],
		    [ -3*2.54-2.4+19.5/2, -1.35+6/2 ]
		], [
		    "traco_tba1e_dual",
		    "DC/DC Converter",
		    "https://www.tracopower.com/sites/default/files/products/datasheets/tba1e_datasheet.pdf",
		    [ undef, "+Vin", "-Vin", undef, "-Vout", "Common",  "+Vout" ],
		    [ -3*2.54-2.4+19.5/2, -1.35+6/2 ]
		], [
		    "traco_tba1hi_single",
		    "DC/DC Converter",
		    "https://www.tracopower.com/sites/default/files/products/datasheets/tba1hi_datasheet.pdf",
		    [ undef, "+Vin", "-Vin", undef, undef, "-Vout", undef,  "+Vout" ],
		    [ -3*2.54-2.4+19.5/2, -1.35+6/2 ]
		], [
		    "traco_tba1hi_dual",
		    "DC/DC Converter",
		    "https://www.tracopower.com/sites/default/files/products/datasheets/tba1hi_datasheet.pdf",
		    [ undef, "+Vin", "-Vin", undef, undef, "-Vout", "Common",  "+Vout" ],
		    [ -3*2.54-2.4+19.5/2, -1.35+6/2 ]
		], [
		    "traco_tea1e",
		    "DC/DC Converter",
		    "https://www.tracopower.com/sites/default/files/products/datasheets/tea1e_datasheet.pdf",
		    [ undef, qw| +Vin -Vin |, undef, "-Vout", undef, "+Vout" ],
		    [ -3*2.54-2.4+19.5/2, -0.9+6/2 ]
		], [
		    "traco_tea1hi",
		    "DC/DC Converter",
		    "https://www.tracopower.com/sites/default/files/products/datasheets/tea1hi_datasheet.pdf",
		    [ undef, qw| +Vin -Vin |, undef, undef, "-Vout", undef, "+Vout" ],
		    [ -3*2.54-2.4+19.5/2, -0.9+6/2 ]
		]
	    ]
	], [
	    [ [ 19.5, 6.10 ], 0 ],
	    [
		{ "a" => [ 0.5, 0.25, undef, 2.54 ], },
		[[ 'ydx', "a", 0, -3*2.54, (2.54)x6 ]],
		[
		    "traco_tma_single",
		    "DC/DC Converter",
		    "https://www.tracopower.com/sites/default/files/products/datasheets/tma_datasheet.pdf",
		    [ undef, "+Vin", "-Vin", undef, "-Vout", undef,  "+Vout" ],
		    [ -3*2.54-2.1+19.5/2, -1.3+6.1/2 ]
		], [
		    "traco_tma_dual",
		    "DC/DC Converter",
		    "https://www.tracopower.com/sites/default/files/products/datasheets/tma_datasheet.pdf",
		    [ undef, "+Vin", "-Vin", undef, "-Vout", "Common",  "+Vout" ],
		    [ -3*2.54-2.1+19.5/2, -1.3+6.1/2 ]
		], [
		    "traco_tmv_single",
		    "DC/DC Converter",
		    "https://www.tracopower.com/sites/default/files/products/datasheets/tmv_datasheet.pdf",
		    [ undef, "+Vin", "-Vin", undef, undef, "-Vout", undef,  "+Vout" ],
		    [ -3*2.54-2.1+19.5/2, -1.25+6.1/2 ]
		], [
		    "traco_tmv_dual",
		    "DC/DC Converter",
		    "https://www.tracopower.com/sites/default/files/products/datasheets/tmv_datasheet.pdf",
		    [ undef, "+Vin", "-Vin", undef, undef, "-Vout", "Common",  "+Vout" ],
		    [ -3*2.54-2.1+19.5/2, -1.25+6.1/2 ]
		], [
		    "traco_tra1_single",
		    "DC/DC Converter",
		    "https://www.tracopower.com/sites/default/files/products/datasheets/tra1_datasheet.pdf",
		    [ undef, "+Vin", "-Vin", undef, "-Vout", undef,  "+Vout" ],
		    [ -3*2.54-2.3+19.5/2, -1.3+6.1/2 ]
		], [
		    "traco_tra1_dual",
		    "DC/DC Converter",
		    "https://www.tracopower.com/sites/default/files/products/datasheets/tra1_datasheet.pdf",
		    [ undef, "+Vin", "-Vin", undef, "-Vout", "Common",  "+Vout" ],
		    [ -3*2.54-2.3+19.5/2, -1.3+6.1/2 ]
		], [
		    "traco_trv1_single",
		    "DC/DC Converter",
		    "https://www.tracopower.com/sites/default/files/products/datasheets/tmv_datasheet.pdf",
		    [ undef, "+Vin", "-Vin", undef, undef, "-Vout", undef,  "+Vout" ],
		    [ -3*2.54-2.35+19.5/2, -1.3+6.1/2 ]
		]
	    ]
	], [
	    [ [ 19.5, 7.10 ], 0 ],
	    [
		{ "a" => [ 0.5, 0.25, undef, 2.54 ], },
		[[ 'ydx', "a", 0, -3*2.54, (2.54)x6 ]],
		[
		    "traco_tma_24_single",
		    "DC/DC Converter",
		    "https://www.tracopower.com/sites/default/files/products/datasheets/tma_datasheet.pdf",
		    [ undef, "+Vin", "-Vin", undef, "-Vout", undef,  "+Vout" ],
		    [ -3*2.54-2.1+19.5/2, -1.3+7.1/2 ]
		], [
		    "traco_tma_24_dual",
		    "DC/DC Converter",
		    "https://www.tracopower.com/sites/default/files/products/datasheets/tma_datasheet.pdf",
		    [ undef, "+Vin", "-Vin", undef, "-Vout", "Common",  "+Vout" ],
		    [ -3*2.54-2.1+19.5/2, -1.3+7.1/2 ]
		], [
		    "traco_tmv_24_single",
		    "DC/DC Converter",
		    "https://www.tracopower.com/sites/default/files/products/datasheets/tmv_datasheet.pdf",
		    [ undef, "+Vin", "-Vin", undef, undef, "-Vout", undef,  "+Vout" ],
		    [ -3*2.54-2.1+19.5/2, -1.25+7.1/2 ]
		], [
		    "traco_tmv_24_dual",
		    "DC/DC Converter",
		    "https://www.tracopower.com/sites/default/files/products/datasheets/tmv_datasheet.pdf",
		    [ undef, "+Vin", "-Vin", undef, undef, "-Vout", "Common",  "+Vout" ],
		    [ -3*2.54-2.1+19.5/2, -1.25+7.1/2 ]
		], [
		    "traco_tra1_24_single",
		    "DC/DC Converter",
		    "https://www.tracopower.com/sites/default/files/products/datasheets/tra1_datasheet.pdf",
		    [ undef, "+Vin", "-Vin", undef, "-Vout", undef,  "+Vout" ],
		    [ -3*2.54-2.3+19.5/2, -1.3+7.1/2 ]
		], [
		    "traco_tra1_24_dual",
		    "DC/DC Converter",
		    "https://www.tracopower.com/sites/default/files/products/datasheets/tra1_datasheet.pdf",
		    [ undef, "+Vin", "-Vin", undef, "-Vout", "Common",  "+Vout" ],
		    [ -3*2.54-2.3+19.5/2, -1.3+7.1/2 ]
		], [
		    "traco_trv1_24_single",
		    "DC/DC Converter",
		    "https://www.tracopower.com/sites/default/files/products/datasheets/tmv_datasheet.pdf",
		    [ undef, "+Vin", "-Vin", undef, undef, "-Vout", undef,  "+Vout" ],
		    [ -3*2.54-2.35+19.5/2, -1.3+7.1/2 ]
		], [
		    "traco_tmap_single",
		    "DC/DC Converter",
		    "https://www.tracopower.com/sites/default/files/products/datasheets/tmap_datasheet.pdf",
		    [ undef, "+Vin", "-Vin", undef, "-Vout", undef,  "+Vout" ],
		    [ -3*2.54-2.1+19.5/2, -1.8+7.1/2 ]
		], [
		    "traco_tmap_dual",
		    "DC/DC Converter",
		    "https://www.tracopower.com/sites/default/files/products/datasheets/tmap_datasheet.pdf",
		    [ undef, "+Vin", "-Vin", undef, "-Vout", "Common",  "+Vout" ],
		    [ -3*2.54-2.1+19.5/2, -1.8+7.1/2 ]
		]
	    ]
	], [
	    [ [ 19.5, 7.50 ], 0 ],
	    [
		{ "a" => [ 0.5, 0.25, undef, 2.54 ], },
		[[ 'ydx', "a", 0, -3*2.54, (2.54)x6 ]],
		[
		    "traco_tmh_single",
		    "DC/DC Converter",
		    "https://www.tracopower.com/sites/default/files/products/datasheets/tmh_datasheet.pdf",
		    [ undef, "+Vin", "-Vin", undef, "-Vout", undef,  "+Vout" ],
		    [ -3*2.54-2.1+19.5/2, -1.25+7.5/2 ]
		], [
		    "traco_tmh_dual",
		    "DC/DC Converter",
		    "https://www.tracopower.com/sites/default/files/products/datasheets/tmh_datasheet.pdf",
		    [ undef, "+Vin", "-Vin", undef, "-Vout", "Common",  "+Vout" ],
		    [ -3*2.54-2.1+19.5/2, -1.25+7.5/2 ]
		], [
		    "traco_tmv_hi_single",
		    "DC/DC Converter",
		    "https://www.tracopower.com/sites/default/files/products/datasheets/tmv_hi_datasheet.pdf",
		    [ undef, "+Vin", "-Vin", undef, undef, "-Vout", undef,  "+Vout" ],
		    [ -3*2.54-2.1+19.5/2, -1.55+7.5/2 ]
		], [
		    "traco_tmv_hi_dual",
		    "DC/DC Converter",
		    "https://www.tracopower.com/sites/default/files/products/datasheets/tmv_hi_datasheet.pdf",
		    [ undef, "+Vin", "-Vin", undef, undef, "-Vout", "Common",  "+Vout" ],
		    [ -3*2.54-2.1+19.5/2, -1.55+7.5/2 ]
		], [
		    "traco_tmv2hi_single",
		    "DC/DC Converter",
		    "https://www.tracopower.com/sites/default/files/products/datasheets/tmv2hi_datasheet.pdf",
		    [ undef, "+Vin", "-Vin", undef, undef, "-Vout", undef,  "+Vout" ],
		    [ -3*2.54-2.1+19.5/2, -1.8+7.5/2 ]
		], [
		    "traco_tmv2hi_dual",
		    "DC/DC Converter",
		    "https://www.tracopower.com/sites/default/files/products/datasheets/tm2hi_datasheet.pdf",
		    [ undef, "+Vin", "-Vin", undef, undef, "-Vout", "Common",  "+Vout" ],
		    [ -3*2.54-2.1+19.5/2, -1.8+7.5/2 ]
		]
	    ]
	], [
	    [ [ 19.5, 7.62 ], 0 ],
	    [
		{ "a" => [ 0.5, 0.25, undef, 2.54 ], },
		[[ 'ydx', "a", 0, -3*2.54, (2.54)x6 ]],
		[
		    "traco_tra3_single",
		    "DC/DC Converter",
		    "https://www.tracopower.com/sites/default/files/products/datasheets/tra3_datasheet.pdf",
		    [ undef, "+Vin", "-Vin", undef, "-Vout", undef,  "+Vout" ],
		    [ -3*2.54-2.1+19.5/2, -1.3+7.62/2 ]
		]
	    ]
	], [
	    [ [ 19.55, 7.60 ], 0 ],
	    [
		{ "a" => [ 0.5, 0.25, undef, 2.54 ], },
		[[ 'ydx', "a", 0, -3*2.54, (2.54)x6 ]],
		[
		    "traco_tba2_single",
		    "DC/DC Converter",
		    "https://www.tracopower.com/sites/default/files/products/datasheets/tba2_datasheet.pdf",
		    [ undef, "+Vin", "-Vin", undef, "-Vout", undef,  "+Vout" ],
		    [ -3*2.54-2.4+19.55/2, -1.5+7.6/2 ]
		], [
		    "traco_tba2_dual",
		    "DC/DC Converter",
		    "https://www.tracopower.com/sites/default/files/products/datasheets/tba2_datasheet.pdf",
		    [ undef, "+Vin", "-Vin", undef, "-Vout", "Common",  "+Vout" ],
		    [ -3*2.54-2.4+19.55/2, -1.5+7.6/2 ]
		]
	    ]
	], [
	    [ [ 19.60, 9.90 ], 0 ],
	    [
		{ "a" => [ 0.5, 0.25, undef, 2 ], },
		[[ 'ydx', "a", 0, -4*2, (2)x8 ]],
		[
		    "traco_trv1m_single",
		    "DC/DC Converter",
		    "https://www.tracopower.com/sites/default/files/products/datasheets/trv1m_datasheet.pdf",
		    [ undef, "+Vin", "-Vin", (undef)x4, "-Vout", undef,  "+Vout" ],
		    [ 4*2+1.8-19.6/2, -2.3+9.9/2 ]
		], [
		    "traco_trv1m_dual",
		    "DC/DC Converter",
		    "https://www.tracopower.com/sites/default/files/products/datasheets/trv1m_datasheet.pdf",
		    [ undef, "+Vin", "-Vin", (undef)x4, "-Vout", "Common",  "+Vout" ],
		    [ 4*2+1.8-19.6/2, -2.3+9.9/2 ]
		]
	    ]
	], [
	    [ [ 21.8, 9.1 ], 0 ],
	    [
		{ "a" => [ 0.5, 0.25, undef, 2.54 ], },
		[[ 'ydx', "a", 0, -3.5*2.54, (2.54)x7 ]],
		[
		    "traco_tecN_single",
		    "DC/DC Converter",
		    "https://www.tracopower.com/sites/default/files/products/datasheets/tec2_datasheet.pdf tec2wi tec3 tec3wi",
		    [ undef, qw| -Vin +Vin Ctrl |, undef, qw| NC +Vout -Vout NC | ],
		    [ 3.5*2.54+2-21.8/2, -3.2+9.1/2 ]
		], [
		    "traco_tecN_dual",
		    "DC/DC Converter",
		    "https://www.tracopower.com/sites/default/files/products/datasheets/tec2_datasheet.pdf tec2wi tec3 tec3wi",
		    [ undef, qw| -Vin +Vin Ctrl |, undef, qw| NC +Vout Common -Vout | ],
		    [ 3.5*2.54+2-21.8/2, -3.2+9.1/2 ]
		], [
		    "traco_tmr6,9_single",
		    "DC/DC Converter",
		    "https://www.tracopower.com/sites/default/files/products/datasheets/tmr6_datasheet.pdf tmr6wi tmr9 tmr9wi",
		    [ undef, qw| -Vin +Vin Ctrl |, undef, undef, qw| +Vout -Vout NC | ],
		    [ -3.5*2.54-2+21.8/2, -3.2+9.1/2 ]
		], [
		    "traco_tmr6,9_dual",
		    "DC/DC Converter",
		    "https://www.tracopower.com/sites/default/files/products/datasheets/tmr6_datasheet.pdf tmr6wi tmr9 tmr9wi",
		    [ undef, qw| -Vin +Vin Ctrl |, undef, undef, qw| +Vout Common -Vout | ],
		    [ -3.5*2.54-2+21.8/2, -3.2+9.1/2 ]
		]
	    ]
	], [
	    [ [ 21.8, 9.2 ], 0 ],
	    [
		{ "a" => [ 0.5, 0.25, undef, 2.54 ], },
		[[ 'ydx', "a", 0, -3.5*2.54, (2.54)x7 ]],
		[
		    "traco_tmr2,3X_single",
		    "DC/DC Converter",
		    "https://www.tracopower.com/sites/default/files/products/datasheets/tmr2_datasheet.pdf tmr3 tmr3wi",
		    [ undef, qw| -Vin +Vin Ctrl |, undef, qw| NC +Vout -Vout NC | ],
		    [ -3.5*2.54-2+21.8/2, -3.2-0.25/2+9.2/2 ]
		], [
		    "traco_tmr2,3X_dual",
		    "DC/DC Converter",
		    "https://www.tracopower.com/sites/default/files/products/datasheets/tmr2_datasheet.pdf tmr3 tmr3wi",
		    [ undef, qw| -Vin +Vin Ctrl |, undef, qw| NC +Vout Common -Vout | ],
		    [ -3.5*2.54-2+21.8/2, -3.2-0.25/2+9.2/2 ]
		], [
		    "traco_tmr3hi_single",
		    "DC/DC Converter",
		    "https://www.tracopower.com/sites/default/files/products/datasheets/tmr3hi_datasheet.pdf",
		    [ undef, qw| -Vin +Vin Ctrl |, undef, undef, qw| +Vout -Vout NC | ],
		    [ -3.5*2.54-2+21.8/2, -3.2-0.25/2+9.2/2 ]
		], [
		    "traco_tmr3hi_dual",
		    "DC/DC Converter",
		    "https://www.tracopower.com/sites/default/files/products/datasheets/tmr3hi_datasheet.pdf",
		    [ undef, qw| -Vin +Vin Ctrl |, undef, undef, qw| +Vout Common -Vout | ],
		    [ -3.5*2.54-2+21.8/2, -3.2-0.25/2+9.2/2 ]
		]
	    ]
	], [
	    [ [ 21.8, 9.3 ], 0 ],
	    [
		{ "a" => [ 0.5, 0.25, undef, 2.54 ], },
		[[ 'ydx', "a", 0, -3.5*2.54, (2.54)x7 ]],
		[
		    "traco_tmr2win_single",
		    "DC/DC Converter",
		    "https://www.tracopower.com/sites/default/files/products/datasheets/tmr2win_datasheet.pdf",
		    [ undef, qw| -Vin +Vin Ctrl |, undef, qw| NC +Vout -Vout NC | ],
		    [ -3.5*2.54-2+21.8/2, -2.5-0.25/2+9.3/2 ]
		], [
		    "traco_tmr2win_dual",
		    "DC/DC Converter",
		    "https://www.tracopower.com/sites/default/files/products/datasheets/tmr2win_datasheet.pdf",
		    [ undef, qw| -Vin +Vin Ctrl |, undef, qw| NC +Vout Common -Vout | ],
		    [ -3.5*2.54-2+21.8/2, -2.5-0.25/2+9.3/2 ]
		], [
		    "traco_tmr2e,3X,4X_single",
		    "DC/DC Converter",
		    "https://www.tracopower.com/sites/default/files/products/datasheets/tmr3e_datasheet.pdf tmr2e tmr3wie tmr4 tmr4wi",
		    [ undef, qw| -Vin +Vin Ctrl |, undef, qw| NC +Vout -Vout NC | ],
		    [ -3.5*2.54-2+21.8/2, -2.7+0.25/2+9.3/2 ]
		], [
		    "traco_tmr3X,4X_dual",
		    "DC/DC Converter",
		    "https://www.tracopower.com/sites/default/files/products/datasheets/tmr3e_datasheet.pdf tme3wie tmr4 tmr4wi",
		    [ undef, qw| -Vin +Vin Ctrl |, undef, qw| NC +Vout Common -Vout | ],
		    [ -3.5*2.54-2+21.8/2, -2.7+0.25/2+9.3/2 ]
		]
	    ]
	], [
	    [ [ 21.8, 9.6 ], 0 ],
	    [
		{ "a" => [ 0.5, 0.25, undef, 2.54 ],
		  "b" => [ 1.0, 0.30, [ undef, (2.5)x5 ], 4.5  ], # case pin standoffs is 2.5mm
		  "c" => [ 0.4, 0.00, [ 0.4, (2.5)x5 ], 4.5  ] }, # case standoffs is 2.5mm
		[[ 'ydx', "a", 0, -3.5*2.54, (2.54)x7     ],
		 [ 'xy' , "b", -10.6/2-0.01, -3.3         ],
		 [ 'xy' , "b",  10.6/2-0.01, -3.3+9.6-0.3 ],
		 [ 'xy' , "c",  10.6/2-0.01, -3.3         ],
		 [ 'xy' , "c", -10.6/2-0.01, -3.3+9.6-0.3 ]],
		[
		    "traco_tmrNwir_single",
		    "DC/DC Converter",
		    "https://www.tracopower.com/sites/default/files/products/datasheets/tmr3wir_datasheet.pdf tmr6wir",
		    [ undef, qw| -Vin +Vin Ctrl |, undef, undef, qw| +Vout -Vout NC Case Case StandOff StandOff | ],
		    [ -3.5*2.54-2.02+21.8/2, -3.3-0.25/2+9.6/2 ]
		], [
		    "traco_tmrNwir_dual",
		    "DC/DC Converter",
		    "https://www.tracopower.com/sites/default/files/products/datasheets/tmr3wir_datasheet.pdf tmr6wir",
		    [ undef, qw| -Vin +Vin Ctrl |, undef, undef, qw| +Vout Common -Vout Case Case StandOff StandOff | ],
		    [ -3.5*2.54-2.02+21.8/2, -3.3-0.25/2+9.6/2 ]
		], [
		    "traco_tvn3_single",
		    "DC/DC Converter",
		    "https://www.tracopower.com/sites/default/files/products/datasheets/tvn3_datasheet.pdf",
		    [ undef, qw| -Vin +Vin Ctrl |, undef, qw| NC +Vout -Vout NC Case Case StandOff StandOff | ],
		    [ -3.5*2.54-2.02+21.8/2, -3.3-0.25/2+9.6/2 ]
		], [
		    "traco_tvn3_dual",
		    "DC/DC Converter",
		    "https://www.tracopower.com/sites/default/files/products/datasheets/tvn3_datasheet.pdf",
		    [ undef, qw| -Vin +Vin Ctrl |, undef, qw| NC +Vout Common -Vout Case Case StandOff StandOff | ],
		    [ -3.5*2.54-2.02+21.8/2, -3.3-0.25/2+9.6/2 ]
		]
	    ]
	], [
	    [ [ 22.0, 7.5 ], 0 ],
	    [
		{ "a" => [ 0.5, 0.25, undef, 2.54 ], },
		[[ 'ydx', "a", 0, -3*2.54, (2.54)x6 ]],
		[
		    "traco_tmv_en_single",
		    "DC/DC Converter",
		    "https://www.tracopower.com/sites/default/files/products/datasheets/tmv_en_datasheet.pdf",
		    [ undef, qw| +Vin -Vin |, undef, undef, "-Vout", undef, "+Vout" ],
		    [ -3*2.54-3.5+22/2, -2.0+0.25/2+7.5/2 ]
		], [
		    "traco_tmv_en_dual",
		    "DC/DC Converter",
		    "https://www.tracopower.com/sites/default/files/products/datasheets/tmv_en_datasheet.pdf",
		    [ undef, qw| +Vin -Vin |, undef, undef, qw| -Vout Common +Vout | ],
		    [ -3*2.54-3.5+22/2, -2.0+0.25/2+7.5/2 ]
		]
	    ]
	], [
	    [ [ 23.8, 13.4 ], 0 ],
	    [
		{ "a" => [ 0.5, 0.25, undef, 2.54 ], },
		[[ 'ydx', "a",  10.16/2, -3.5*2.54, ( 2.54)x7 ],
		 [ 'ydx', "a", -10.16/2,  3.5*2.54, (-2.54)x7 ]],
		[
		    "traco_thi2m_single",
		    "DC/DC Converter",
		    "https://www.tracopower.com/sites/default/files/products/datasheets/thi2m_datasheet.pdf",
		    [ undef, "-Vin", (undef)x5, qw| NC NC +Vout -Vout |, (undef)x5, "+Vin" ],
		    [ 3.5*2.54+3-23.8/2, 10.16/2+1.62-13.4/2 ]
		], [
		    "traco_thi2m_dual",
		    "DC/DC Converter",
		    "https://www.tracopower.com/sites/default/files/products/datasheets/thi2m_datasheet.pdf",
		    [ undef, "-Vin", (undef)x5, qw| NC Common +Vout -Vout |, (undef)x5, "+Vin" ],
		    [ 3.5*2.54+3-23.8/2, 10.16/2+1.62-13.4/2 ]
		]
	    ]
	], [
	    [ [ 23.8, 13.7 ], 0 ],
	    [
		{ "a" => [ 0.5, 0, undef, 2.54 ], },
		[[ 'ydx', "a",  10.16/2, -3.5*2.54, ( 2.54)x7 ],
		 [ 'ydx', "a", -10.16/2,  3.5*2.54, (-2.54)x7 ]],
		[
		    "traco_tel2,10X_single",
		    "DC/DC Converter",
		    "https://www.tracopower.com/sites/default/files/products/datasheets/tel2_datasheet.pdf tel10 tel10wi",
		    [ undef, "-Vin", (undef)x5, qw| NC NC +Vout -Vout |, (undef)x5, "+Vin" ],
		    [ -3.5*2.54-3+23.8/2 , -10.16/2-1.77+13.7/2 ]
		], [
		    "traco_tel2,10X_dual",
		    "DC/DC Converter",
		    "https://www.tracopower.com/sites/default/files/products/datasheets/tel2_datasheet.pdf tel10 tel10wi",
		    [ undef, "-Vin", (undef)x5, qw| NC Common +Vout -Vout |, (undef)x5, "+Vin" ],
		    [ -3.5*2.54-3+23.8/2 , -10.16/2-1.77+13.7/2 ]
		], [
		    "traco_tel12X_single",
		    "DC/DC Converter",
		    "https://www.tracopower.com/sites/default/files/products/datasheets/tel12_datasheet.pdf 12wi",
		    [ undef, "-Vin", (undef)x6, qw| NC +Vout -Vout |, (undef)x5, "+Vin" ],
		    [ -3.5*2.54-3+23.8/2 , -10.16/2-1.77+13.7/2 ]
		], [
		    "traco_tel12X_dual",
		    "DC/DC Converter",
		    "https://www.tracopower.com/sites/default/files/products/datasheets/tel12_datasheet.pdf 12wi",
		    [ undef, "-Vin", (undef)x6, qw| Common +Vout -Vout |, (undef)x5, "+Vin" ],
		    [ -3.5*2.54-3+23.8/2 , -10.16/2-1.77+13.7/2 ]
		], [
		    "traco_thl3wi_single",
		    "DC/DC Converter",
		    "https://www.tracopower.com/sites/default/files/products/datasheets/thl3wi_datasheet.pdf",
		    [ undef, qw| -Vin Ctrl |, (undef)x4, qw| NC NC +Vout -Vout |, (undef)x5, "+Vin" ],
		    [ -3.5*2.54-3+23.8/2 , -10.16/2-1.77+13.7/2 ]
		], [
		    "traco_thl3wi_dual",
		    "DC/DC Converter",
		    "https://www.tracopower.com/sites/default/files/products/datasheets/thl3wi_datasheet.pdf",
		    [ undef, qw| -Vin Ctrl |, (undef)x4, qw| NC Common +Vout -Vout |, (undef)x5, "+Vin" ],
		    [ -3.5*2.54-3+23.8/2 , -10.16/2-1.77+13.7/2 ]
		]
	    ]
	], [
	    [ [ 24.1, 14.0 ], 1 ],
	    [
		{ "a" => [ 0.5, 0, undef, 2.54 ], },
		[[ 'ydx', "a",  10.16/2, -24.1/2+3.2           , ( 2.54)x7 ],
		 [ 'ydx', "a", -10.16/2, -24.1/2+3.2+15.24+2.54, (-2.54)x7 ]],
		[
		    "traco_tel8X_single",
		    "DC/DC Converter",
		    "https://www.tracopower.com/sites/default/files/products/datasheets/tel8_datasheet.pdf 8wi",
		    [ undef, "-Vin", (undef)x5, qw| NC NC +Vout -Vout|, (undef)x5, "+Vin" ],
		    [ -3.5*2.54-3.2+24.1/2 , 0 ]
		], [
		    "traco_tel8X_dual",
		    "DC/DC Converter",
		    "https://www.tracopower.com/sites/default/files/products/datasheets/tel8_datasheet.pdf 8wi",
		    [ undef, "-Vin", (undef)x5, qw| NC Common +Vout -Vout|, (undef)x5, "+Vin" ],
		    [ -3.5*2.54-3.2+24.1/2 , 0 ]
		]
	    ]
	], [
	    [ [ 24.3, 14.4 ], 0 ],
	    [
		{ "a" => [ 0.5, 0, undef, 2.54 ], },
		[[ 'ydx', "a",  10.16/2, -3.5*2.54, ( 2.54)x7 ],
		 [ 'ydx', "a", -10.16/2,  3.5*2.54, (-2.54)x7 ]],
		[
		    "traco_timX_single",
		    "DC/DC Converter",
		    "https://www.tracopower.com/sites/default/files/products/datasheets/tim2_datasheet.pdf tim3_5",
		    [ undef, qw| -Vin Ctrl |, (undef)x4, qw| NC NC +Vout -Vout |, (undef)x5, "+Vin" ],
		    [ -3.5*2.54-3.2+24.3/2 , -10.16/2-2.1+14.4/2 ]
		], [
		    "traco_timX_dual",
		    "DC/DC Converter",
		    "https://www.tracopower.com/sites/default/files/products/datasheets/tim2_datasheet.pdf tim3_5",
		    [ undef, qw| -Vin Ctrl |, (undef)x4, qw| NC Common +Vout -Vout |, (undef)x5, "+Vin" ],
		    [ -3.5*2.54-3.2+24.3/2 , -10.16/2-2.1+14.4/2 ]
		]
	    ]
	], [
	    [ [ 25.4, 25.4 ], 0 ],
	    [
		{ "a" => [ 0,8, 0, undef, 5.08 ], },
		[[ 'ydx', "a", -10.16, -2.54, 5.08 ],
		 [ 'yx' , "a",  10.16, -10.16, 0, 10.16 ],
		 [ 'yx' , "a", -10.16,  10.16 ]],
		[
		    "traco_thd15_single", # thd15_dual is bigger, se below
		    "DC/DC Converter",
		    "https://www.tracopower.com/sites/default/files/products/datasheets/thd15_datasheet.pdf",
		    [ undef, qw| +Vin -Vin +Vout |, undef, qw| -Vout Ctrl | ],
		    [ 10.16+2.5-25.4/2 , 10.16+2.5-25.4/2 ]
		]
	    ], [
		{ "a" => [ 1.0, 0, undef, 5.08 ], },
		[[ 'ydx', "a", -10.16, -2.54, 5.08 ],
		 [ 'yx' , "a",  10.16, -10.16, 0, 10.16 ],
		 [ 'yx' , "a", -10.16,  10.16 ]],
		[
		    "traco_thl10_single",
		    "DC/DC Converter",
		    "https://www.tracopower.com/sites/default/files/products/datasheets/thl10_datasheet.pdf",
		    [ undef, qw| +Vin -Vin +Vout |, undef, qw| -Vout | ],
		    [ 10.16+2.5-25.4/2 , 10.16+2.5-25.4/2 ]
		], [
		    "traco_thl10_dual",
		    "DC/DC Converter",
		    "https://www.tracopower.com/sites/default/files/products/datasheets/thl10_datasheet.pdf",
		    [ undef, qw| +Vin -Vin +Vout Common -Vout | ],
		    [ 10.16+2.5-25.4/2 , 10.16+2.5-25.4/2 ]
		], [
		    "traco_thl10wi_single",
		    "DC/DC Converter",
		    "https://www.tracopower.com/sites/default/files/products/datasheets/thl10wi_datasheet.pdf",
		    [ undef, qw| +Vin -Vin +Vout |, undef, qw| -Vout Ctrl | ],
		    [ 10.16+2.5-25.4/2 , 10.16+2.5-25.4/2 ]
		], [
		    "traco_thlXX_single",
		    "DC/DC Converter",
		    "https://www.tracopower.com/sites/default/files/products/datasheets/thl15wi_datasheet.pdf thl20wi thl25 thl25wi thn15 thn15n thn15wi thn15wir thn20 thn20wi thn30 thn30wi",
		    [ undef, qw| +Vin -Vin +Vout Trim -Vout Ctrl | ],
		    [ 10.16+2.5-25.4/2 , 10.16+2.5-25.4/2 ]
		], [
		    "traco_thlXX_dual",
		    "DC/DC Converter",
		    "https://www.tracopower.com/sites/default/files/products/datasheets/thl10wi_datasheet.pdf thl15wi thl20wi_dual thl25 thl25wi thn15 thn15n thn15wi thn15wir thn20 thn20wi thn30 thn30wi",
		    [ undef, qw| +Vin -Vin +Vout Common -Vout Ctrl | ],
		    [ 10.16+2.5-25.4/2 , 10.16+2.5-25.4/2 ]
		]
	    ], [
		{ "a" => [ 1.0, 0, undef, 5.08 ], },
		[[ 'ydx', "a", -10.16, -2.54, 5.08, 7.62 ],
		 [ 'yx' , "a",  10.16, -10.16, 0, 10.16 ]],
		[
		    "traco_thn10,20,30wir_single",
		    "DC/DC Converter",
		    "https://www.tracopower.com/sites/default/files/products/datasheets/thn10wir_datasheet.pdf thn20wir thn30wir",
		    [ undef, qw| +Vin -Vin Ctrl +Vout Trim -Vout | ],
		    [ 10.16+2.5-25.4/2 , 10.16+2.5-25.4/2 ]
		], [
		    "traco_thn10,20,30wir_dual",
		    "DC/DC Converter",
		    "https://www.tracopower.com/sites/default/files/products/datasheets/thn10wir_datasheet.pdf thn20wir thn30wir",
		    [ undef, qw| +Vin -Vin Ctrl +Vout Common -Vout | ],
		    [ 10.16+2.5-25.4/2 , 10.16+2.5-25.4/2 ]
		]
	    ], [
		{ "a" => [ 0.6, 0, undef, 5.08 ], },
		[[ 'ydx', "a",  10.16, -10.16, 5.08 ],
		 [ 'yx' , "a", -10.16,  10.16, 0, -10.16 ]],
		[
		    "traco_tmps03,05_single",
		    "DC/DC Converter",
		    "https://www.tracopower.com/sites/default/files/products/datasheets/tnos03_datasheet.pdf tmps05",
		    [ undef, qw| N L NC -Vout +Vout | ],
		    [ -10.16-2.54+25.4/2 , 10.16+2.54-25.4/2 ]
		]
	    ]
	], [
	    [ [ 25.4, 27.9 ], 0 ],
	    [
		{ "a" => [ 0.8, 0, undef, 5.08 ], },
		[[ 'ydx', "a", -10.16, -2.54, 5.08 ],
		 [ 'yx' , "a",  10.16, -10.16, 0, 10.16 ],
		 [ 'yx' , "a", -10.16,  10.16 ]],
		[
		    "traco_thd15_dual",
		    "DC/DC Converter",
		    "https://www.tracopower.com/sites/default/files/products/datasheets/thd15_datasheet.pdf",
		    [ undef, qw| +Vin -Vin +Vout Common -Vout Ctrl | ],
		    [ 10.16+2.5-25.4/2 , 10.16+2.5-27.9/2 ]
		]
	    ]
	], [
	    [ [ 23.88, 27.94 ], 0 ],
	    [
		{ "a" => [ 0.8, 0, undef, 5.08 ], },
		[[ 'ydx', "a", -10.16, -2.54, 5.08 ],
		 [ 'yx' , "a",  10.16, -10.16, 0, 10.16 ],
		 [ 'yx' , "a", -10.16,  10.16 ]],
		[
		    "traco_tonN_sigle",
		    "DC/DC Converter",
		    "https://www.tracopower.com/sites/default/files/products/datasheets/ton15_datasheet.pdf ton15wi",
		    [ undef, qw| +Vin -Vin +Vout Trim -Vout Ctrl | ],
		    [ 0 , 10.16+3.81-27.94/2 ]
		]
	    ]
	], [
	    [ [ 25.95, 9.25 ], 0 ],
	    [
		{ "a" => [ 0.5, 0, undef, 2.54 ], },
		[[ 'ydx', "a", 0, -2.54*4, (2.54)x8 ]],
		[
		    "traco_tmr2wi_single",
		    "DC/DC Converter",
		    "https://www.tracopower.com/sites/default/files/products/datasheets/tmr2wi_datasheet.pdf",
		    [ undef, qw| -Vin +Vin Ctrl |, (undef)x2, qw| +Vout NC NC -Vout | ],
		    [ -4*2.54-2.0+25.95/2 , 0.25/2-3.0+9.25/2 ]
		], [
		    "traco_tmr2wi_dual",
		    "DC/DC Converter",
		    "https://www.tracopower.com/sites/default/files/products/datasheets/tmr2wi_datasheet.pdf",
		    [ undef, qw| -Vin +Vin Ctrl |, (undef)x2, qw| +Vout Common NC -Vout | ],
		    [ -4*2.54-2.0+25.95/2 , 0.25/2-3.0+9.25/2 ]
		]
	    ]
	], [
	    [ [ 31.8, 20.3 ], 0 ],
	    [
		{ "a" => [ 0.5, 0, undef, 2.54 ], },
		[[ 'ydx', "a",  15.22/2, -5.5*2.54, ( 2.54)x11 ],
		 [ 'ydx', "a", -15.22/2,  5.5*2.54, (-2.54)x11 ]],
		[
		    "traco_ten4_single",
		    "DC/DC Converter",
		    "https://www.tracopower.com/sites/default/files/products/datasheets/ten4_datasheet.pdf",
		    [ (undef)x2, qw| -Vin -Vin |, (undef)x5, undef, undef, "NC", (undef)x2, "+Vout", undef, "-Vout",
		      (undef)x5, "+Vin", "+Vin" ],
		    [ -4.5*2.54-4.54 + 31.8/2, -15.22/2-2.4 + 20.3/2 ]
		], [
		    "traco_ten4_dual",
		    "DC/DC Converter",
		    "https://www.tracopower.com/sites/default/files/products/datasheets/ten4_datasheet.pdf",
		    [ (undef)x2, qw| -Vin -Vin |, (undef)x5, "Common", undef, "-Vout", (undef)x2, "+Vout", undef, "Common",
		      (undef)x5, "+Vin", "+Vin" ],
		    [ -4.5*2.54-4.54 + 31.8/2, -15.22/2-2.4 + 20.3/2 ]
		], [
		    "traco_ten5_single",
		    "DC/DC Converter",
		    "https://www.tracopower.com/sites/default/files/products/datasheets/ten5_datasheet.pdf",
		    [ (undef)x2, qw| -Vin -Vin |, (undef)x5, undef, undef, "NC", (undef)x2, "+Vout", undef, "-Vout",
		      (undef)x5, "+Vin", "+Vin" ],
		    [ -4.5*2.54-4.5 + 31.8/2, -15.22/2-2.54 + 20.3/2 ]
		], [
		    "traco_ten5_dual",
		    "DC/DC Converter",
		    "https://www.tracopower.com/sites/default/files/products/datasheets/ten5_datasheet.pdf",
		    [ (undef)x2, qw| -Vin -Vin |, (undef)x5, "Common", undef, "-Vout", (undef)x2, "+Vout", undef, "Common",
		      (undef)x5, "+Vin", "+Vin" ],
		    [ -4.5*2.54-4.5 + 31.8/2, -15.22/2-2.54 + 20.3/2 ]
		], [
		    "traco_thd10n,win_single",
		    "DC/DC Converter",
		    "https://www.tracopower.com/sites/default/files/products/datasheets/thd10n_datasheet.pdf thd10win",
		    [ undef, qw| Ctrl -Vin -Vin |, (undef)x5, undef, undef, "NC", (undef)x2, "+Vout", undef, "-Vout",
		      (undef)x5, "+Vin", "+Vin" ],
		    [ 4.5*2.54+4.5 - 31.8/2, -15.22/2-2.54 + 20.3/2 ]
		], [
		    "traco_thd10n,win_dual",
		    "DC/DC Converter",
		    "https://www.tracopower.com/sites/default/files/products/datasheets/thd10n_datasheet.pdf thd10win",
		    [ undef, qw| Ctrl -Vin -Vin |, (undef)x5, "Common", undef, "-Vout", (undef)x2, "+Vout", undef, "Common",
		      (undef)x5, "+Vin", "+Vin" ],
		    [ 4.5*2.54+4.5 - 31.8/2, -15.22/2-2.54 + 20.3/2 ]
		], [
		    "traco_thi3_single",
		    "DC/DC Converter",
		    "https://www.tracopower.com/sites/default/files/products/datasheets/thi3_datasheet.pdf",
		    [ undef, qw| -Vin -Vin |, (undef)x7, undef, undef, qw| -Vout +Vout |, undef, undef,
		      (undef)x7, "+Vin", "+Vin" ],
		    [ -5.5*2.54-2 + 31.8/2, -15.22/2-2.54 + 20.3/2 ]
		], [
		    "traco_thi3_dual",
		    "DC/DC Converter",
		    "https://www.tracopower.com/sites/default/files/products/datasheets/thi3_datasheet.pdf",
		    [ undef, qw| -Vin -Vin |, (undef)x7, qw| Common Common |, undef, "-Vout", undef, "+Vout",
		      (undef)x7, "+Vin", "+Vin" ],
		    [ -5.5*2.54-2 + 31.8/2, -15.22/2-2.54 + 20.3/2 ]
		], [
		    "traco_tri10_single",
		    "DC/DC Converter",
		    "https://www.tracopower.com/sites/default/files/products/datasheets/tri10_datasheet.pdf",
		    [ undef, qw| +Vin |, (undef)x9, undef, qw| -Vout +Vout |, undef, undef,
		      (undef)x7, "-Vin", "-Vin" ],
		    [ 5.5*2.54+2 - 31.8/2, -15.22/2-2.54 + 20.3/2 ]
		], [
		    "traco_tri10_dual",
		    "DC/DC Converter",
		    "https://www.tracopower.com/sites/default/files/products/datasheets/tri10_datasheet.pdf",
		    [ undef, qw| +Vin |, (undef)x9, "Common", undef, "-Vout", undef, "+Vout",
		      (undef)x7, "-Vin", "-Vin" ],
		    [ 5.5*2.54+2 - 31.8/2, -15.22/2-2.54 + 20.3/2 ]
		]

	    ], [
		{ "a" => [ 0.5, 0, undef, 2.54 ], },
		[[ 'ydx', "a",  15.24/2, -5.5*2.54, ( 2.54)x11 ],
		 [ 'ydx', "a", -15.24/2,  5.5*2.54, (-2.54)x11 ]],
		[
		    "traco_ten5wi_single",
		    "DC/DC Converter",
		    "https://www.tracopower.com/sites/default/files/products/datasheets/ten5wi_datasheet.pdf",
		    [ (undef)x2, qw| -Vin -Vin |, (undef)x5, undef, undef, "NC", (undef)x2, "+Vout", undef, "-Vout",
		      (undef)x5, "+Vin", "+Vin" ],
		    [ -4.5*2.54-4.5 + 31.8/2, -15.24/2-2.4 + 20.3/2 ]
		], [
		    "traco_ten5wi_dual",
		    "DC/DC Converter",
		    "https://www.tracopower.com/sites/default/files/products/datasheets/ten5wi_datasheet.pdf",
		    [ (undef)x2, qw| -Vin -Vin |, (undef)x5, "Common", undef, "-Vout", (undef)x2, "+Vout", undef, "Common",
		      (undef)x5, "+Vin", "+Vin" ],
		    [ -4.5*2.54-4.5 + 31.8/2, -15.24/2-2.4 + 20.3/2 ]
		], [
		    "traco_ten8wi_single",
		    "DC/DC Converter",
		    "https://www.tracopower.com/sites/default/files/products/datasheets/ten8wi_datasheet.pdf",
		    [ undef, qw| Ctrl -Vin -Vin |, (undef)x5, "NC", undef, "NC", (undef)x2, "+Vout", undef, "-Vout",
		      (undef)x5, "+Vin", "+Vin" ],
		    [0,-15.24/2 - 2.53 + 20.3/2]
		], [
		    "traco_ten8wi_dual",
		    "DC/DC Converter",
		    "https://www.tracopower.com/sites/default/files/products/datasheets/ten8wi_datasheet.pdf",
		    [ undef, qw| Ctrl -Vin -Vin |, (undef)x5, "Common", undef, "-Vout", (undef)x2, "+Vout", undef, "Common",
		      (undef)x5, "+Vin", "+Vin" ],
		    [0,-15.24/2 - 2.53 + 20.3/2]
		], [
		    "traco_thd10_single",
		    "DC/DC Converter",
		    "https://www.tracopower.com/sites/default/files/products/datasheets/thd10_datasheet.pdf",
		    [ (undef)x2, qw| -Vin -Vin |, (undef)x5, undef, undef, "NC", (undef)x2, "+Vout", undef, "-Vout",
		      (undef)x5, "+Vin", "+Vin" ],
		    [ -4.5*2.54-4.5 + 31.8/2, -15.24/2-2.5 + 20.3/2 ]
		], [
		    "traco_thd10_dual",
		    "DC/DC Converter",
		    "https://www.tracopower.com/sites/default/files/products/datasheets/thd10_datasheet.pdf",
		    [ (undef)x2, qw| -Vin -Vin |, (undef)x5, "Common", undef, "-Vout", (undef)x2, "+Vout", undef, "Common",
		      (undef)x5, "+Vin", "+Vin" ],
		    [ -4.5*2.54-4.5 + 31.8/2, -15.24/2-2.5 + 20.3/2 ]
		]
	    ], [
		{ "a" => [ 0.5, 0, undef, 2.54 ], },
		[[ 'ydx', "a",  15.25/2, -5.5*2.54, ( 2.54)x11 ],
		 [ 'ydx', "a", -15.25/2,  5.5*2.54, (-2.54)x11 ]],
		[
		    "traco_tem2,3_single",
		    "DC/DC Converter",
		    "https://www.tracopower.com/sites/default/files/products/datasheets/tem2_datasheet.pdf tem3",
		    [ undef, qw| +Vin NC NC |, (undef)x6, qw| -Vout +Vout -Vin -Vin +Vout -Vout |,
		      (undef)x6, qw| NC NC +Vin | ],
		    [ -27.94/2-2+31.8/2, -15.25/2-2.54+ 20.3/2]
		], [
		    "traco_tem2,3_dual",
		    "DC/DC Converter",
		    "https://www.tracopower.com/sites/default/files/products/datasheets/tem2_datasheet.pdf tem3",
		    [ undef, qw| +Vin -Vout Common |, (undef)x6, qw| Common +Vout -Vin -Vin +Vout Common |,
		      (undef)x6, qw| Common -Vout +Vin | ],
		    [ -27.94/2-2+31.8/2, -15.25/2-2.54+ 20.3/2]
		]
	    ], [
		{ "a" => [ 0.6, 0, undef, 2.54 ], },
		[[ 'ydx', "a",  15.2/2, -5.5*2.54, ( 2.54)x11 ],
		 [ 'ydx', "a", -15.2/2,  5.5*2.54, (-2.54)x11 ]],
		[
		    "traco_thb3,thp3_single",
		    "DC/DC Converter",
		    "https://www.tracopower.com/sites/default/files/products/datasheets/thb3_datasheet.pdf thp3",
		    [ undef, qw| +Vin |, (undef)x9, undef, qw| -Vout +Vout |, undef, undef,
		      (undef)x7, qw| -Vin -Vin | ],
		    [ 27.94/2+2-31.8/2, -15.2/2-2.54 + 20.3/2]
		], [
		    "traco_thb3,thp3_dual",
		    "DC/DC Converter",
		    "https://www.tracopower.com/sites/default/files/products/datasheets/thb3_datasheet.pdf thp3",
		    [ undef, qw| +Vin |, (undef)x9, "Common", undef, "-Vout", undef, "+Vout",
		      (undef)x7, qw| -Vin -Vin | ],
		    [ 27.94/2+2-31.8/2, -15.2/2-2.54 + 20.3/2]
		]
	    ], [
		{ "a" => [ 0.6, 0, undef, 2.54 ], },
		[[ 'ydx', "a",  15.22/2, -5.5*2.54, ( 2.54)x11 ],
		 [ 'ydx', "a", -15.22/2,  5.5*2.54, (-2.54)x11 ]],
		[
		    "traco_thr3wi,tri3,6_single",
		    "DC/DC Converter",
		    "https://www.tracopower.com/sites/default/files/products/datasheets/thr3wi_datasheet.pdf tri3 tri6",
		    [ undef, qw| +Vin |, (undef)x9, undef, qw| -Vout +Vout |, undef, undef,
		      (undef)x7, qw| -Vin -Vin | ],
		    [ 27.94/2+2-31.8/2, 0 ]
		], [
		    "traco_thr3wi,tri3,6_dual",
		    "DC/DC Converter",
		    "https://www.tracopower.com/sites/default/files/products/datasheets/thr3wi_datasheet.pdf tri3 tri6",
		    [ undef, qw| +Vin |, (undef)x9, "Common", undef, "-Vout", undef, "+Vout",
		      (undef)x7, qw| -Vin -Vin | ],
		    [ 27.94/2+2-31.8/2, 0 ]
		]
	    ], [
		{ "a" => [ 0.6, 0, undef, 2.54 ], },
		[[ 'ydx', "a",  15.24/2, -5.5*2.54, ( 2.54)x11 ],
		 [ 'ydx', "a", -15.24/2,  5.5*2.54, (-2.54)x11 ]],
		[
		    "traco_ten3,6,10wirh_single",
		    "DC/DC Converter",
		    "https://www.tracopower.com/sites/default/files/products/datasheets/ten3wirh_datasheet.pdf ten6wirh ten10wirh",
		    [ undef, qw| Ctrl -Vin -Vin |, (undef)x5, "NC", undef, "NC", (undef)x2, "+Vout", undef, "-Vout",
		      (undef)x5, "+Vin", "+Vin" ],
		    [ -5.5*2.54-2 + 31.8/2, 0]
		], [
		    "traco_ten3,6,10wirh_dual",
		    "DC/DC Converter",
		    "https://www.tracopower.com/sites/default/files/products/datasheets/ten3wirh_datasheet.pdf ten6wirh ten10wirh",
		    [ undef, qw| Ctrl -Vin -Vin |, (undef)x5, "Common", undef, "-Vout", (undef)x2, "+Vout", undef, "Common",
		      (undef)x5, "+Vin", "+Vin" ],
		    [ -5.5*2.54-2 + 31.8/2, 0]
		], [
		    "traco_ten3,6,10wirh_trim_single",
		    "DC/DC Converter",
		    "https://www.tracopower.com/sites/default/files/products/datasheets/ten3wirh_datasheet.pdf ten6wirh ten10wirh",
		    [ undef, qw| Ctrl -Vin -Vin |, (undef)x5, "NC", "trim", "NC", (undef)x2, "+Vout", undef, "-Vout",
		      (undef)x5, "+Vin", "+Vin" ],
		    [ -5.5*2.54-2 + 31.8/2, 0]
		], [
		    "traco_ten3,6,10wirh_trim_dual",
		    "DC/DC Converter",
		    "https://www.tracopower.com/sites/default/files/products/datasheets/ten3wirh_datasheet.pdf ten6wirh ten10wirh",
		    [ undef, qw| Ctrl -Vin -Vin |, (undef)x5, "Common", "trim", "-Vout", (undef)x2, "+Vout", undef, "Common",
		      (undef)x5, "+Vin", "+Vin" ],
		    [ -5.5*2.54-2 + 31.8/2, 0]
		], [
		    "traco_thm3,6,10X_a_single",
		    "DC/DC Converter",
		    "https://www.tracopower.com/sites/default/files/products/datasheets/thm3_datasheet.pdf thm3wi thm6 thm6wi thm10 thm10wi",
		    [ undef, "+Vin", (undef)x9, undef, qw| -Vout +Vout |, undef, undef, (undef)x7, "-Vin", "-Vin" ],
		    [ -5.5*2.54-2 + 31.8/2, -15.24/2-2.54+ 20.3/2]
		], [
		    "traco_thm3,6,10X_a_dual",
		    "DC/DC Converter",
		    "https://www.tracopower.com/sites/default/files/products/datasheets/thm3_datasheet.pdf thm3wi thm6 thm6wi thm10 thm10wi",
		    [ undef, "+Vin", (undef)x9, "Common", undef, "-Vout", undef, "+Vout", (undef)x7, "-Vin", "-Vin" ],
		    [ -5.5*2.54-2 + 31.8/2, -15.24/2-2.54+ 20.3/2]
		], [
		    "traco_thm3,6,10X_b_single",
		    "DC/DC Converter",
		    "https://www.tracopower.com/sites/default/files/products/datasheets/thm3_datasheet.pdf thm3wi thm6 thm6wi thm10 thm10wi",
		    [ undef, undef, "-Vin", (undef)x7, undef, "NC", (undef)x2,
		      "+Vout", undef, "-Vout", (undef)x5, "+Vin", "+Vin" ],
		    [ -5.5*2.54-2 + 31.8/2, -15.24/2-2.54+ 20.3/2]
		], [
		    "traco_thm3,6,10X_b_dual",
		    "DC/DC Converter",
		    "https://www.tracopower.com/sites/default/files/products/datasheets/thm3_datasheet.pdf thm3wi thm6 thm6wi thm10 thm10wi",
		    [ undef, undef, "-Vin", (undef)x7, undef, "-Vout", (undef)x2,
		      "+Vout", undef, "Common", (undef)x5, "+Vin", "+Vin" ],
		    [ -5.5*2.54-2 + 31.8/2, -15.24/2-2.54+ 20.3/2]
		], [
		    "traco_thm3,6,10X_c_single",
		    "DC/DC Converter",
		    "https://www.tracopower.com/sites/default/files/products/datasheets/thm3_datasheet.pdf thm3wi thm6 thm6wi thm10 thm10wi",
		    [ undef, "Ctrl", "-Vin", (undef)x7, undef, "NC", (undef)x2,
		      "+Vout", undef, "-Vout", (undef)x5, "+Vin", "+Vin" ],
		    [ -5.5*2.54-2 + 31.8/2, -15.24/2-2.54+ 20.3/2]
		], [
		    "traco_thm3,6,10X_c_dual",
		    "DC/DC Converter",
		    "https://www.tracopower.com/sites/default/files/products/datasheets/thm3_datasheet.pdf thm3wi thm6 thm6wi thm10 thm10wi",
		    [ undef, "Ctrl", "-Vin", (undef)x7, undef, "-Vout", (undef)x2,
		      "+Vout", undef, "Common", (undef)x5, "+Vin", "+Vin" ],
		    [ -5.5*2.54-2 + 31.8/2, -15.24/2-2.54+ 20.3/2]
		], [
		    "traco_thm3,6,10X_t_single",
		    "DC/DC Converter",
		    "https://www.tracopower.com/sites/default/files/products/datasheets/thm3_datasheet.pdf thm3wi thm6 thm6wi thm10 thm10wi",
		    [ undef, undef, "-Vin", (undef)x7, "trim", undef, (undef)x2,
		      "+Vout", undef, "-Vout", (undef)x5, "+Vin", "+Vin" ],
		    [ -5.5*2.54-2 + 31.8/2, -15.24/2-2.54+ 20.3/2]
		], [
		    "traco_thm3,6,10X_t_dual",
		    "DC/DC Converter",
		    "https://www.tracopower.com/sites/default/files/products/datasheets/thm3_datasheet.pdf thm3wi thm6 thm6wi thm10 thm10wi",
		    [ undef, undef, "-Vin", (undef)x7, "trim", "-Vout", (undef)x2,
		      "+Vout", undef, "Common", (undef)x5, "+Vin", "+Vin" ],
		    [ -5.5*2.54-2 + 31.8/2, -15.24/2-2.54+ 20.3/2]
		], [
		    "traco_thm3,6,10X_ct_single",
		    "DC/DC Converter",
		    "https://www.tracopower.com/sites/default/files/products/datasheets/thm3_datasheet.pdf thm3wi thm6 thm6wi thm10 thm10wi",
		    [ undef, "Ctrl", "-Vin", (undef)x7, "trim", undef, (undef)x2,
		      "+Vout", undef, "-Vout", (undef)x5, "+Vin", "+Vin" ],
		    [ -5.5*2.54-2 + 31.8/2, -15.24/2-2.54+ 20.3/2]
		], [
		    "traco_thm3,6,10X_ct_dual",
		    "DC/DC Converter",
		    "https://www.tracopower.com/sites/default/files/products/datasheets/thm3_datasheet.pdf thm3wi thm6 thm6wi thm10 thm10wi",
		    [ undef, "Ctrl", "-Vin", (undef)x7, "trim", "-Vout", (undef)x2,
		      "+Vout", undef, "Common", (undef)x5, "+Vin", "+Vin" ],
		    [ -5.5*2.54-2 + 31.8/2, -15.24/2-2.54+ 20.3/2]
		], [
		    "traco_tvn5wi_single",
		    "DC/DC Converter",
		    "https://www.tracopower.com/sites/default/files/products/datasheets/tvn5wi_datasheet.pdf",
		    [ undef, qw| +Vin +Vin Case |, (undef)x8, qw| Case Trim -Vout +Vout |,
		      (undef)x6, qw| Ctrl -Vin -Vin | ],
		    [ 5.5*2.54+2 - 31.8/2, -15.24/2 - 2.53 + 20.3/2 ]
		], [
		    "traco_tvn5wi_dual",
		    "DC/DC Converter",
		    "https://www.tracopower.com/sites/default/files/products/datasheets/tvn5wi_datasheet.pdf",
		    [ undef, qw| +Vin +Vin Case |, (undef)x6, qw| Common +Vout1 Case Trim -Vout2 Common |,
		      (undef)x6, qw| Ctrl -Vin -Vin | ],
		    [ 5.5*2.54+2 - 31.8/2, -15.24/2 - 2.53 + 20.3/2 ]
		]
	    ], [
		{ "a" => [ 0.6, 0, undef, 2.54 ], },
		[[ 'ydx', "a",  15.24/2, -31.8/2+2       , (2.54)x11 ],
		 [ 'ydx', "a", -15.24/2, -31.8/2+2+27.94, (-2.54)x11 ]],
		[
		    "traco_ten10wirh_single",
		    "DC/DC Converter",
		    "https://www.tracopower.com/sites/default/files/products/datasheets/ten10wirh_datasheet.pdf ten6wirh ten8",
		    [ undef, qw| Ctrl -Vin -Vin |, (undef)x5, "NC", undef, "NC", (undef)x2,
		      "+Vout", undef, "-Vout", (undef)x5, qw| +Vin +Vin | ],
		    [0,0]
		], [
		    "traco_ten10wirh_trim_single",
		    "DC/DC Converter",
		    "https://www.tracopower.com/sites/default/files/products/datasheets/ten10wirh_datasheet.pdf ten6wirh",
		    [ undef, qw| Ctrl -Vin -Vin |, (undef)x5, qw| NC Trim NC |, (undef)x2,
		      "+Vout", undef, "-Vout", (undef)x5, qw| +Vin +Vin | ],
		    [0,0]
		], [
		    "traco_ten10wirh_dual",
		    "DC/DC Converter",
		    "https://www.tracopower.com/sites/default/files/products/datasheets/ten10wirh_datasheet.pdf ten6wirh ten8",
		    [ undef, qw| Ctrl -Vin -Vin |, (undef)x5, "Common", undef, "-Vout", (undef)x2,
		      "+Vout", undef, "Common", (undef)x5, qw| +Vin +Vin | ],
		    [0,0]
		], [
		    "traco_ten10wirh_trim_dual",
		    "DC/DC Converter",
		    "https://www.tracopower.com/sites/default/files/products/datasheets/ten10wirh_datasheet.pdf ten6wirh",
		    [ undef, qw| Ctrl -Vin -Vin |, (undef)x5, qw| Common Trim -Vout |, (undef)x2,
		      "+Vout", undef, "Common", (undef)x5, qw| +Vin +Vin | ],
		    [0,0]
		]
	    ]

	], [
	    [ [ 31.8, 20.3 ], [0,-1.5,0,0] ],
	    [
		{ "a" => [ 0.5, 0, undef, 2.54 ], },
		[[ 'ydx', "a", +15.24/2, -31.8/2+4.5-2.54      , ( 2.54)x11 ],
		 [ 'ydx', "a", -15.24/2, -31.8/2+4.5+2.54+22.86, (-2.54)x11 ]],
		[
		    "traco_tel5_single",
		    "DC/DC Converter",
		    "https://www.tracopower.com/sites/default/files/products/datasheets/tel5_datasheet.pdf ten3 ten3n ten3win ten6n ten6win",
		    [ (undef)x2, qw| -Vin -Vin |, (undef)x5, undef, undef, "NC", (undef)x2,
		      "+Vout", undef, "-Vout", (undef)x5, qw| +Vin +Vin | ],
		    [ 0, 0 ]
		], [
		    "traco_tel5_dual",
		    "DC/DC Converter",
		    "https://www.tracopower.com/sites/default/files/products/datasheets/tel5_datasheet.pdf ten3 ten3n ten3win ten6n ten6win",
		    [ (undef)x2, qw| -Vin -Vin |, (undef)x5, "Common", undef, "-Vout", (undef)x2,
		      "+Vout", undef, "Common", (undef)x5, qw| +Vin +Vin | ],
		    [0,0]
		]
	    ], [
		{ "a" => [ 0.6, 0, undef, 2.54 ], },
		[[ 'ydx', "a", +15.24/2, -31.8/2+4.5-2.54      , ( 2.54)x11 ],
		 [ 'ydx', "a", -15.24/2, -31.8/2+4.5+2.54+22.86, (-2.54)x11 ]],
		[
		    "traco_thb6_single",
		    "DC/DC Converter",
		    "https://www.tracopower.com/sites/default/files/products/datasheets/thb6_datasheet.pdf",
		    [ undef, qw| +Vin |, (undef)x9, undef, qw| -Vout +Vout |,
		      undef, undef, (undef)x7, qw| -Vin -Vin | ],
		    [ 0, 0 ]
		], [
		    "traco_thb6_dual",
		    "DC/DC Converter",
		    "https://www.tracopower.com/sites/default/files/products/datasheets/thb6_datasheet.pdf",
		    [ undef, qw| +Vin |, (undef)x9, "Common", undef, "-Vout", undef, "+Vout",
		      (undef)x7, qw| -Vin -Vin | ],
		    [0,0]
		]
	    ]
	], [
	    [ [ 31.8, 20.32 ], 0 ],
	    [
		{ "a" => [ 0.5, 0, undef, 2.54 ], },
		[[ 'ydx', "a", +15.24/2, -31.8/2+4.5-2.54      , ( 2.54)x11 ],
		 [ 'ydx', "a", -15.24/2, -31.8/2+4.5+2.54+22.86, (-2.54)x11 ]],
		[
		    "traco_thd12,15X_single",
		    "DC/DC Converter",
		    "https://www.tracopower.com/sites/default/files/products/datasheets/thd12_datasheet.pdf thd12wi thd15n thd15win",
		    [ undef, qw| Ctrl -Vin -Vin |, (undef)x5, "NC", undef, "NC", (undef)x2,
		      "+Vout", undef, "-Vout", (undef)x5, "+Vin", "+Vin" ],
		    [ -5.5*2.54-2.54 + 31.8/2, -15.24/2-2.54+ 20.32/2]
		], [
		    "traco_thd12,15X_dual",
		    "DC/DC Converter",
		    "https://www.tracopower.com/sites/default/files/products/datasheets/thd12_datasheet.pdf thd12wi thd15n thd15win",
		    [ undef, qw| Ctrl -Vin -Vin |, (undef)x5, "Common", undef, "-Vout", (undef)x2,
		      "+Vout", undef, "Common", (undef)x5, "+Vin", "+Vin" ],
		    [ -5.5*2.54-2.54 + 31.8/2, -15.24/2-2.54+ 20.32/2]
		]
	    ]
	], [
	    [ [ 31.8, 20.32 ], [0,-1.5,0,0] ],
	    [
		{ "a" => [ 0.5, 0, undef, 2.54 ], },
		[[ 'ydx', "a", +15.24/2, -31.8/2+4.5-2.54      , ( 2.54)x11 ],
		 [ 'ydx', "a", -15.24/2, -31.8/2+4.5+2.54+22.86, (-2.54)x11 ]],
		[
		    "traco_tem3n_single",
		    "DC/DC Converter",
		    "https://www.tracopower.com/sites/default/files/products/datasheets/tem3n_datasheet.pdf ten8",
		    [ undef, qw| +Vin NC NC |, (undef)x6, qw| -Vout +Vout -Vin -Vin +Vout -Vout |,
		      (undef)x6, qw| NC NC +Vin | ],
		    [ 0, 0 ]
		], [
		    "traco_tem3n_dual",
		    "DC/DC Converter",
		    "https://www.tracopower.com/sites/default/files/products/datasheets/tem3n_datasheet.pdf ten8",
		    [ undef, qw| +Vin -Vout Common |, (undef)x6, qw| Common +Vout -Vin -Vin +Vout Common |,
		      (undef)x6, qw| Common -Vout +Vin | ],
		    [0,0]
		]
	    ]
	], [
	    [ [ 32.0, 20.0 ], 0 ],
	    [
		{ "a" => [ 0.5, 0, undef, 2.24 ], },
		[[ 'ydx', "a", +15.24/2, -5.5*2.54, ( 2.54)x11 ],
		 [ 'ydx', "a", -15.24/2,  5.5*2.54, (-2.54)x11 ]],
		[
		    "traco_tel3_single",
		    "DC/DC Converter",
		    "https://www.tracopower.com/sites/default/files/products/datasheets/tel3_datasheet.pdf",
		    [ undef, qw| +Vin NC NC |, (undef)x6, qw| -Vout +Vout -Vin -Vin +Vout -Vout |,
		      (undef)x6, qw| NC NC +Vin | ],
		    [ -5.5*2.54 - 2.0 + 32/2, -15.24/2 - 2.4 + 20/2 ]
		], [
		    "traco_tel3_dual",
		    "DC/DC Converter",
		    "https://www.tracopower.com/sites/default/files/products/datasheets/tel3_datasheet.pdf",
		    [ undef, qw| +Vin -Vout Common |, (undef)x6, qw| Common +Vout -Vin -Vin +Vout Common |,
		      (undef)x6, qw| Common -Vout +Vin | ],
		    [ -5.5*2.54 - 2.0 + 32/2, -15.24/2 - 2.4 + 20/2 ]
		], [
		    "traco_tel3_np,ten3wi_single",
		    "DC/DC Converter",
		    "https://www.tracopower.com/sites/default/files/products/datasheets/tel3_datasheet.pdf ten3wi",
		    [ (undef)x2, qw| -Vin -Vin |, (undef)x5, undef, undef, "NC", (undef)x2,
		      "+Vout", undef, "-Vout", (undef)x5, qw| +Vin +Vin | ],
		    [ -5.5*2.54 - 2.0 + 32/2, -15.24/2 - 2.4 + 20/2 ]
		], [
		    "traco_tel3_np,ten3wi_dual",
		    "DC/DC Converter",
		    "https://www.tracopower.com/sites/default/files/products/datasheets/tel3_datasheet.pdf ten3wi",
		    [ (undef)x2, qw| -Vin -Vin |, (undef)x5, "Common", undef, "-Vout", (undef)x2,
		      "+Vout", undef, "Common", (undef)x5, qw| +Vin +Vin | ],
		    [ -5.5*2.54 - 2.0 + 32/2, -15.24/2 - 2.4 + 20/2 ]
		], [
		    "traco_thi2_single",
		    "DC/DC Converter",
		    "https://www.tracopower.com/sites/default/files/products/datasheets/thi2_datasheet.pdf",
		    [ undef, qw| +Vin +Vin |, (undef)x9, qw| -Vout +Vout |, (undef)x9, qw| -Vin -Vin | ],
		    [ -5.5*2.54 - 2.0 + 32/2, -15.24/2 - 2.4 + 20/2 ]
		], [
		    "traco_thi2_dual",
		    "DC/DC Converter",
		    "https://www.tracopower.com/sites/default/files/products/datasheets/thi2_datasheet.pdf",
		    [ undef, qw| +Vin +Vin |, (undef)x7, qw| Common Common |, undef,  "-Vout", undef, "+Vout",
		      (undef)x7, qw| -Vin -Vin | ],
		    [ -5.5*2.54 - 2.0 + 32/2, -15.24/2 - 2.4 + 20/2 ]
		]
	    ]
	], [
	    [ [ 32.6, 20.4 ], 0 ],
	    [
		{ "a" => [ 0.6, 0, undef, 5.08 ], },
		[[ 'ydx', "a",  15.24/2, -5.5*2.54, ( 2.54)x11 ],
		 [ 'ydx', "a", -15.24/2,  5.5*2.54, (-2.54)x11 ]],
		[
		    "traco_tyl_single",
		    "DC/DC Converter",
		    "https://www.tracopower.com/sites/default/files/products/datasheets/tyl_tvl_datasheet.pdf",
		    [ undef, "-Vin", (undef)x8, "-Vout", undef, qw| -Vout +Vout |, undef, "+Vout",
		      (undef)x8, "+Vin" ],
		    [ -5.5*2.54 - 2.33 + 32.6/2, -15.24/2 - 2.58 + 20.4/2 ]
		], [
		    "traco_tyl_dual",
		    "DC/DC Converter",
		    "https://www.tracopower.com/sites/default/files/products/datasheets/tyl_tvl_datasheet.pdf",
		    [ undef, "-Vin", (undef)x8, "-Vout", undef, qw| Common Common |, undef, "+Vout",
		      (undef)x8, "+Vin" ],
		    [ -5.5*2.54 - 2.33 + 32.6/2, -15.24/2 - 2.58 + 20.4/2 ]
		]
	    ]
#zzzzz
#...........

#############

	], [
	    [ [ 38.1, 25.4 ], 0 ],
	    [
		{ "a" => [ 1, 0, undef, 5.59 ], },
		[[ 'xdy' , "a", -35.05/2, -2.82, -5.59 ],
		 [ 'xdy', "a",  35.05/2, 11.18, -16.24, -6.12 ]],
		[
		    "traco_tpp15a_d",
		    "AC/DC Converter",
		    "https://www.tracopower.com/sites/default/files/products/datasheets/tpp15a_d_datasheet.pdf",
		    [ undef, qw| N L Trim -Vout +Vout | ],
		    [ 35.05/2 + 1.5 - 38.1/2, -2.82 + 15.5 - 25.4/2 ]
		]
	    ]

	], [
	    [ [ 60, 40 ], 2 ],
	    [
		{ "a" => [ 0.8, 0, undef, 5.08 ], },
		[[ 'xdy', "a", -40.64/2,  20.32/2-2.54, (-5.08)x4 ],
		 [ 'xy' , "a",  40.64/2, -20.32/2, 20.32/2 ]],
		[ # first footprint
		    "traco_phv",
		    "High Voltage Power Supplies",
		    "https://www.tracopower.com/sites/default/files/products/datasheets/phv_datasheet.pdf",
		    [ undef, qw| +Vin -Vin Vadj Vref |, undef, qw| Common Vout | ], # pin-out
		    [ 0.02, 0.04 ], # offset to apply to body
		], [ # next footprint
		    "traco_phv_rc",
		    "High Voltage Power Supplies",
		    "https://www.tracopower.com/sites/default/files/products/datasheets/phv_datasheet.pdf", # docs
		    [ undef, qw| +Vin -Vin Vadj Vref on/off Common Vout | ],
		    [ 0.02, 0.04 ],
		]
	    ],
	],
    );

    my @aa = (
	[
	    (undef)x4,
	    \&silk_crectr, [ $origin, [ 32.0, 20.0 ], 0 ],
	    { "a" => [ 0.5, 0, undef, 2.54 ], },
	    [[ 'ydx', "a",  15.24/2, -32/2+2      , (2.54)x11 ],
	     [ 'ydx', "a", -15.24/2, -32/2+2+27.94, (-2.54)x11 ]],
	    [
		"traco_tel3_single",
		"3W dc/dc converter",
		"https://www.tracopower.com/sites/default/files/products/datasheets/tel3_datasheet.pdf",
		[ undef, qw| +Vin NC NC |, (undef)x6, qw| -Vout +Vout -Vin -Vin +Vout -Vout |, (undef)x6, qw| NC NC +Vin | ],
	    ], [
		"traco_tel3_dual",
		"3W dc/dc converter",
		"https://www.tracopower.com/sites/default/files/products/datasheets/tel3_datasheet.pdf",
		[ undef, qw| +Vin -Vout Common |, (undef)x6, qw| Common +Vout -Vin -Vin +Vout Common |,
		  (undef)x6, qw| Common -Vout +Vin | ],
	    ], [
		"traco_tel3np_single",
		"3W dc/dc converter",
		"https://www.tracopower.com/sites/default/files/products/datasheets/tel3_datasheet.pdf",
		[ (undef)x2, qw| -Vin -Vin |, (undef)x7, "NC", (undef)x2, "+Vout", undef, "-Vout", (undef)x5, qw| +Vin +Vin |],
	    ], [
		"traco_tel3np_dual",
		"3W dc/dc converter",
		"https://www.tracopower.com/sites/default/files/products/datasheets/tel3_datasheet.pdf",
		[ (undef)x2, qw| -Vin -Vin |, (undef)x5, "Common", undef, "-Vout",
		  (undef)x2, "+Vout", undef, "Common", (undef)x5, qw| +Vin +Vin |],
	    ]
	],

	[
	    (undef)x4,
	    \&silk_crectr, [ $origin, [ 40.6, 25.4 ], 0 ],
	    { "a" => [ 1, 0, undef, 5.08 ], },
	    [[ 'xdy', "a", -35.56/2, +20.32/2-2.54, -5.08, -10.16 ],
	     [ 'xdy', "a",  35.56/2, +20.32/2     , (-10.16)x3 ]],
	    [
		"traco_ten20wirh_single",
		"20W dc/dc converter",
		"https://www.tracopower.com/sites/default/files/products/datasheets/ten20wirh_datasheet.pdf",
		[ undef, qw| +Vin -Vin Ctrl +Vout -Vout Trim | ],
	    ], [
		"traco_ten20wirh_dual",
		"20W dc/dc converter",
		"https://www.tracopower.com/sites/default/files/products/datasheets/ten20wirh_datasheet.pdf",
		[ undef, qw| +Vin -Vin Ctrl +Vout Common -Vout | ],
	    ]
	],

	[
	    (undef)x4,
	    \&silk_crectr, [ $origin, [ 50.8, 25.4 ], 1.5 ],
	    { "a" => [ 1, 0, undef, 5.08 ], },
	    [[ 'xdy', "a", -50.8/2+15.2      , -25.4/2+10.2+5.08, -5.08 ],
	     [ 'xdy', "a", -50.8/2+15.2+20.32, -25.4/2+2.5+20.32, (-10.16)x2 ],
	     [ 'xy' , "a", -50.8/2+15.2      , -25.4/2+2.5 ]],
	    [
		"traco_tel15_single",
		"15W dc/dc converter",
		"https://www.tracopower.com/sites/default/files/products/datasheets/tel15_datasheet.pdf",
		[ undef, qw| +Vin -Vin +Vout |, undef, "-Vout" ],
	    ], [
		"traco_tel15_dual",
		"15W dc/dc converter",
		"https://www.tracopower.com/sites/default/files/products/datasheets/tel15_datasheet.pdf",
		[ undef, qw| +Vin -Vin +Vout Common -Vout | ],
	    ], [ # same as tel15_*
		"traco_ten10_single",
		"10W 15W dc/dc converter",
		"https://www.tracopower.com/sites/default/files/products/datasheets/ten10_datasheet.pdf ten15",
		[ undef, qw| +Vin -Vin +Vout |, undef, "-Vout" ],
	    ], [
		"traco_ten10_dual",
		"10W 15W dc/dc converter",
		"https://www.tracopower.com/sites/default/files/products/datasheets/ten10_datasheet.pdf ten15",
		[ undef, qw| +Vin -Vin +Vout Common -Vout | ],
	    ], [
		"traco_ten12wi_single",
		"12W dc/dc converter",
		"https://www.tracopower.com/sites/default/files/products/datasheets/ten12wi_datasheet.pdf",
		[ undef, qw| +Vin -Vin +Vout |, undef, "-Vout" ],
	    ], [
		"traco_ten12wi_dual",
		"12W dc/dc converter",
		"https://www.tracopower.com/sites/default/files/products/datasheets/ten12wi_datasheet.pdf",
		[ undef, qw| +Vin -Vin +Vout Common -Vout | ],
	    ], [
		"traco_ten15wi_single",
		"15W 20W dc/dc converter",
		"https://www.tracopower.com/sites/default/files/products/datasheets/ten15wi_datasheet.pdf ten20",
		[ undef, qw| +Vin -Vin +Vout |, undef, qw| -Vout Ctrl | ],
	    ], [
		"traco_ten15wi_dual",
		"15W dc/dc converter",
		"https://www.tracopower.com/sites/default/files/products/datasheets/ten15wi_datasheet.pdf ten20 ten20win ten20wir",
		[ undef, qw| +Vin -Vin +Vout Common -Vout Ctrl | ],
	    ], [
		"traco_ten20wiX_single",
		"20W dc/dc converter",
		"https://www.tracopower.com/sites/default/files/products/datasheets/ten20win_datasheet.pdf",
		[ undef, qw| +Vin -Vin +Vout Trim -Vout Ctrl | ],
	    ]
	], [
	    (undef)x4,
	    \&silk_crectr, [ $origin, [ 50.8, 25.4 ], 1.5 ],
	    { "a" => [ 1, 0, undef, 5.08 ], },
	    [[ 'xdy', "a", 50.8/2-2.54-45.72, 25.4/2-2.54-2.54, +2.54-7.62, +7.62-17.78 ],
	     [ 'xdy', "a", 50.8/2-2.54      , 25.4/2-2.54     , (-10.16)x2 ]], # 25.4/2-2.54 = 20.32/2 = 10.16
	    [
		"traco_tel30",
		"30W 40W 50W 60W dc/dc converter",
		"https://www.tracopower.com/sites/default/files/products/datasheets/tel30_datasheet.pdf tel30win ten30" .
		    " ten40n ten40wie ten40win ten40wir ten40wirh ten50 ten50win ten50wi ten60n ten60wir",
		[ undef, qw| +Vin -Vin Ctrl +Vout -Vout Trim | ],
	    ], [
		"traco_ten30_dual",
		"30W 40W dc/dc converter",
		"https://www.tracopower.com/sites/default/files/products/datasheets/ten30_datasheet.pdf ten40wie ten40win ten40wir ten40wirh ten60win ten60wir",
		[ undef, qw| +Vin -Vin Ctrl +Vout Common -Vout | ],
	    ], [
		"traco_ten30win_dual",
		"30W 40W dc/dc converter",
		"https://www.tracopower.com/sites/default/files/products/datasheets/ten30win_datasheet.pdf ten40n",
		[ undef, qw| +Vin -Vin Ctrl Vout1 Common Vout2 | ],
	    ], [
		"traco_ten30win_triple",
		"30W dc/dc converter",
		"https://www.tracopower.com/sites/default/files/products/datasheets/ten30win_datasheet.pdf",
		[ undef, qw| +Vin -Vin Ctrl Vout2 Vout3 Common Vout1 | ],
		(undef)x3,
		[[ 'xdy', "a", 50.8/2-2.54-45.72, 20.32/2-7.62, -5.08, -7.62 ],
		 [ 'xdy', "a", 50.8/2-2.54      , 20.32/2     , -5.08, (-7.62)x2 ]],
	    ]

	], [
	    (undef)x4,
	    \&silk_crectr, [ $origin, [ 50.8, 25.4 ], 1.5 ],
	    { "a" => [ 1, 0, undef, 7.62 ], },
	    [[ 'xdy', "a", 50.8/2-2.5-45.72, 25.4/2-2.54-2.54, -7.62, -10.16 ], # kant till pinne 2.54 ???
	     [ 'xdy', "a", 50.8/2-2.5      , 25.4/2-2.54     , (-10.16)x2 ]],
	    [
		"traco_ten40e_single",
		"40W dc/dc converter",
		"https://www.tracopower.com/sites/default/files/products/datasheets/tel40e_datasheet.pdf",
		[ undef, qw| +Vin -Vin Ctrl +Vout -Vout Trim | ],
	    ], [
		"traco_ten40e_dual",
		"40W dc/dc converter",
		"https://www.tracopower.com/sites/default/files/products/datasheets/ten40e_datasheet.pdf",
		[ undef, qw| +Vin -Vin Ctrl +Vout Common -Vout | ],
	    ]
	],

	[
	    (undef)x4,
	    \&silk_crectr, [ $origin, [ 50.8, 40.6 ], 1.5 ],
	    { "a" => [ 1, 0, undef, 5.08 ], },
	    [[ 'xdy', "a",  45.72/2, -40.6/2+5.1+12.7, 5.08, 10.16 ],
	     [ 'xdy', "a", -45.72/2, -40.6/2+5.1     , (10.16)x3 ]],
	    [
		"traco_ten20wi_single",
		"20W 25W 30W dc/dc converter",
		"https://www.tracopower.com/sites/default/files/products/datasheets/ten20wi_datasheet.pdf ten25 ten25wi ten30wi",
		[ undef, qw| +Vin -Vin Ctrl |, undef, qw| +Vout -Vout Trim | ],
	    ], [
		"traco_ten20wi_dual",
		"20W 25W 30W dc/dc converter",
		"https://www.tracopower.com/sites/default/files/products/datasheets/ten20wi_datasheet.pdf ten25 ten25wi ten30wi",
		[ undef, qw| +Vin -Vin Ctrl +Vout Common -Vout Trim | ],
	    ]

	],

	[
	    (undef)x4,
	    \&silk_crectr, [ $origin, [ 50.8, 50.8 ], 2 ],
	    { "a" => [ 1, 0, undef, 5.08 ], },
	    [[ 'xdy', "a", -50.8/2+2.5      , 50.8/2-22.9, -5.08, -10.16 ],
	     [ 'xdy', "a", -50.8/2+2.5+45.72, 50.8/2-10.2, (-7.62)x2, -5.08, -7.62, -5.08,  ]],
	    [
		"traco_ten40_single",
		"30W dc/dc converter",
		"https://www.tracopower.com/sites/default/files/products/datasheets/tel30win_datasheet.pdf",
		[ undef, qw| +Vin -Vin Ctrl NC -Sense +Sense +Vout -Vout Trim | ],
	    ], [
		"traco_ten40_dual_sym",
		"30W dc/dc converter",
		"https://www.tracopower.com/sites/default/files/products/datasheets/ten30win_datasheet.pdf",
		[ undef, qw| +Vin -Vin Ctrl |, undef, qw| Vout1 Common Common Vout2 Trim | ],
	    ], [
		"traco_ten40_dual_asym",
		"30W dc/dc converter",
		"https://www.tracopower.com/sites/default/files/products/datasheets/ten30win_datasheet.pdf",
		[ undef, qw| +Vin -Vin Ctrl Vout1 Common NC NC Vout2 Common | ],
	    ], [
		"traco_ten40_triple",
		"30W dc/dc converter",
		"https://www.tracopower.com/sites/default/files/products/datasheets/ten30win_datasheet.pdf",
		[ undef, qw| +Vin -Vin Ctrl Vout2 Common Vout3 Vout1 Common NC | ],
	    ]

	], [
	    (undef)x4,
	    \&silk_crectr, [ $origin, [ 50.8, 50.8 ], 2 ],
	    { "a" => [ 1, 0, undef, 5.08 ], },
	    [[ 'xdy', "a", -50.8/2+2.5      , 50.8/2-22.9 , -5.08, -10.16 ],
	     [ 'xdy', "a", -50.8/2+2.5+45.72, 50.8/2-17.78, -7.62, -5.08, -7.62, -5.08,  ]],
	    [
		"traco_ten40w_single",
		"40W 60W dc/dc converter",
		"https://www.tracopower.com/sites/default/files/products/datasheets/tel40w_datasheet.pdf ten60",
		[ undef, qw| +Vin -Vin Ctrl -Sense +Sense +Vout -Vout Trim | ],
	    ], [
		"traco_ten40w_dual",
		"40W dc/dc converter",
		"https://www.tracopower.com/sites/default/files/products/datasheets/ten40w_datasheet.pdf",
		[ undef, qw| +Vin -Vin Ctrl +Vout Common Common -Vout Trim | ],
	    ]


	]
    );

    #my @xx = $data[($#data-3)..($#data-1)];
    my @pkgr = pkgr_extract_common_body(@data);
    #print Dumper(\@pkgr);
    for my $pkgr (@pkgr) {
	pkgr_show($pkgr);
	th_generator($pkgr);
    }
}
#gen_power_th();

sub gen_recom_pin() {
    # dc dc converters
    my $name = "recom";
    my $doc_common = "";
    my $drill = 1.0;
    my $cu_dia = drill_to_cudia($drill);
    my $P = 2.54;
    my @pkg = (
	[
	    "ro", "# Recom ECONOLINE DC/DC-Converter\n# https://www.recom-power.com/pdf/Econoline/RO.pdf\n",
	    [-1.9, 1.27-6], [11.5, 6.0],
	    [0,0, "-Vin"], [$P,0, "+Vin"], [2*$P,0, "-Vout"], [3*$P,0, "+Vout"],
	],
	[
	    "re", "# Recom ECONOLINE DC/DC-Converter\n# https://www.recom-power.com/pdf/Econoline/RE.pdf\n",
	    [-2.0, -1.27], [19.6, 6.0],
	    [0,0, "+Vin"], [$P,0, "-Vin"], [3*$P,0, "-Vout",4], [5*$P,0, "+Vout",6],
	],
    );

    for my $pkg (@pkg) {
	my @arr = @$pkg;

	my $file = sprintf("%s_%s.fp", $name, shift @arr);
	my $doc = $doc_common . (shift @arr);
	my $min = shift @arr;
	my $max = vec_add($min, shift @arr);

	element_start($file, $doc);
	while (@arr) {
	    my $r = shift @arr;
	    pin(  $$r[0], $$r[1], $drill, $cu_dia, $$r[2], "", $$r[3]);
	}
	silk_rect($min, $max, 0);
	element_stop();
    }
}
#gen_recom_pin();

##############################
## connectors

sub gen_armprg_sil($) {
    my $dir = shift; # -1, 0, 1
    my @map = ( "_up", "" , "_down" );
    element_start("armprg_sil$map[$dir+1].fp",
"# take a 10pin pin- or socketlist (0.63x0.63mm pins), remove pos 3 and 9
# to simplify pcb design, rewiring done by adapter card
");
    my $p = 2.54;
    {
	my $d = 0.8; # precidip socket pins
	my $D = 1.6;
	if ($dir != 0) {
	    $d = 1.0; # 0.64mm square angled pin list
	    $D = 2.2;
	}
	for my $n (0,1,3,4,5,6,7,9) {
	    pin( $n * $p, 0, $d, $D);
	}
    }

    my $pw = 0.64;		# pin width
    my $a;
    my $b;
    my $d;
    if ($dir == 0) {
	$a = -$p/2;
	$b = +$p/2;
    } else {
	$a = 1.54 + $pw/2;
	$b = 4.84 - $pw/2;
	$a *= $dir;
	$b *= $dir;
	$d = $dir * 6.9;
    }
    my $c = $b - $a;


    silk_start(-$p/2, $a);
    silk_rline(    0,  $c);
    silk_rline( 10*$p,  0);
    silk_rline(    0, -$c);
    silk_rline(-10*$p,   0);
    if ($dir) {
	silk_width(0.12);
	silk_start(-$pw/2, $b);
	silk_rline(  0, $d );
	silk_rline( 9*$p + $pw, 0);
	silk_rline(  0, -$d );

	silk_width(0.32);
    }

    element_stop();
}
#gen_armprg_sil(-1);
#gen_armprg_sil( 0);
#gen_armprg_sil( 1);

sub gen_amphenol_b6251c1_nt3g( ) {
  element_start("amphenol_b6251c1_nt3g.fp", "# BNC P.C. mount recept. jack
# http://www.farnell.com/datasheets/515479.pdf
");
  my $p = 3.175;

  pin( $p,  $p, 1.5, 3.3, "GND", "");
  use_same_pin_no();
  pin( $p, -$p, 1.5, 3.3, "GND", "");
  use_same_pin_no();
  pin(-$p,  $p, 1.5, 3.3, "GND", "");
  use_same_pin_no();
  pin(-$p, -$p, 1.5, 3.3, "GND", "");

  pin( 0, 0, 1.3, 3.0, "RF", "");

  pr("ElementArc [ 0mm 0mm 5.50mm 5.50mm  0 360 0.32mm ]\n");
  pr("ElementArc [ 0mm 0mm 7.25mm 7.25mm  0 360 0.12mm ]\n");
  element_stop();
}
#gen_amphenol_b6251c1_nt3g( );

sub gen_feig_cprm02( $ ) {
  my $side = shift;
  my $str = "";
  if (defined($side) && $side < 0) {
      $side = -1;
      $str = "_mirror"
  } else {
      $side = +1;
  }
  my @name = qw/ DAT CLK TxD GND RxD --- CLS VCC GND --- rf_signal GND /;

  element_start("feig_cpr.m02$str.fp", "# Feig rfid module
# http://www.feig.de/produkte/obid/produktbereiche/obid-classic-pro/lesermodule/id-cprm02-proximity-lesermodule.html
# unfortunately wery sparse with documentation on thier site
");
  my $p = 2.54;
  my $pd = 44.0/2;

  pr("# X1: control connector\n");
  pr("# 2x5pin 2.54mm pitch e.g. http://www1.elfa.se/data1/wwwroot/assets/datasheets/215307serie_eng_tds.pdf\n");
  my $x1 = -$pd + 2.1;
  my $y1 = $pd - 26.1;
  for (my $ix = 0; $ix < 5; $ix++) {
      pin( $side*($x1   ), $y1-$ix*$p, 0.9, 2.0, shift @name);
      pin( $side*($x1-$p), $y1-$ix*$p, 0.9, 2.0, shift @name);
  }
  {
      my $W = 5.06;
      my $L = 5 * $p + 0.1;
      silk_start( $side*($x1 + ($W-$p)/2), $y1 + $p/2 + 0.05);
      silk_rline( 0, -$L);
      silk_rline(-$side*$W,   0);
      silk_rline(  0,  $L);
      silk_rline( $side*$W,   0);
  }

  pr("# X2: rf connector\n");
  pr("# 2pin 2.54mm pitch e.g. http://www1.elfa.se/data1/wwwroot/assets/datasheets/215297serie_eng_tds.pdf\n");
  my $x2 =  $pd - 3.5;
  my $y2 = $pd - 24.0;
  pin( $side*$x2, $y2   , 0.9, 2.0, shift @name, "square");
  pin( $side*$x2, $y2+$p, 0.9, 2.0, shift @name);
  {
      my $W = 2.52;
      my $L = 2 * $p + 0.1;
      silk_start( $side*($x2 + $W/2), $y2 - 2.64/2);
      silk_rline( 0,  $L);
      silk_rline(-$side*$W,   0);
      silk_rline( 0, -$L);
      silk_rline( $side*$W,   0);
  }

  pr("# mounting pins\n");
  pin(  $pd,  $pd, 3.3, 8.0);
  pin( -$pd,  $pd, 3.3, 8.0);
  pin( -$pd, -$pd, 3.3, 8.0);
  pin(  $pd, -$pd, 3.3, 8.0);

  $bbx1 = $bby1 =  25.0;
  $bbx2 = $bby2 = -25.0;
  silk_bb(0.32);
  element_stop();
}
#gen_feig_cprm02( 1);
#gen_feig_cprm02(-1);

sub gen_sil_apem_3() {
    my $doc = "# https://www.apem.com/int/index.php?controller=attachment&id_attachment=67\n\n";
    my @arr = (
	# lead colours: Black Green Purple Yellow Blue Red Orange Orange Orange
	[ "apem_3xxxPBZ", "0V", "Center_Tap_Ref", "Z_Axis_Output", "Y_Axis_Output", "X_Axis_Output", "+V",
	  "Center_Detect", "Pushbutton_1", "Pushbutton_2" ],
	[ "apem_3xxxPB", "0V", "Center_Tap_Ref", "", "Y_Axis_Output", "X_Axis_Output", "+V",
	  "Center_Detect", "Pushbutton_1", "Pushbutton_2" ],
	[ "apem_3xxxZ", "0V", "Center_Tap_Ref", "Z_Axis_Output", "Y_Axis_Output", "X_Axis_Output", "+V",
	  "Center_Detect", ],
	[ "apem_3xxx", "0V", "Center_Tap_Ref", "", "Y_Axis_Output", "X_Axis_Output", "+V",
	  "Center_Detect", ],
    );
    my $sep = [ 2.54, 2.54 ];
    my $drill = lead_to_drill($s2 * 0.635);

    for my $r (@arr) {
	my $name = shift @$r;
	my $N = @$r;
	my $pin_name = [ "",  @$r ];
	gen_pin_matrix($name . "_", $doc, "y", $sep, [ 1, $N ], $drill, undef, $pin_name);
    }
}
#gen_sil_apem_3();

sub gen_apem_3mek() {
    my $name = "apem_3mek";
    my $doc = "# https://www.apem.com/int/index.php?controller=attachment&id_attachment=67\n";

    # p. 2
    my $fw = 42.0;
    my $fh =  4.5;

    my $bd = 38.5;
    my $bh = 20.0;
    my $cw = 4; # cables that exit to the right
    my $cx = triangle_x($bd, $cw)/2;

    my $sr =  3.2/2;
    my $ss = 35.8/2;

    my @bezel = (
	# p. 3, drop in mounting, sub mounting option A and B
	# mounting   bezel       panel_hole  bezel_radie (measured)
	[ "drop in", "circular", 39/2,       65.0/2 ],
	[ "drop in", "square"  , 39/2,       48.5   ],
	[ "sub A"  , "no"      , 35/2,       46.0/2 ], # no bezel, it's the rubber outer dia
	[ "sub B"  , "circular", 31/2,       60.0/2 ],
    );

    my $o = [0,0];
    for my $r (@bezel) {
	my $file = $name . "_" . substr($$r[0],0,1) . substr($$r[1],0,1) . ".fp";
	element_start($file, $doc . "# $$r[0] mounting, $$r[1] bezel\n");
	silk_width(0.12);
	silk_circle($o,$$r[2]);
	silk_circle([ $ss, $ss], $sr);
	silk_circle([-$ss, $ss], $sr);
	silk_circle([-$ss,-$ss], $sr);
	silk_circle([ $ss,-$ss], $sr);
	silk_width();
	silk_start($cx, $cw/2);
	silk_rline(2*$cw, 0);
	silk_start($cx, -$cw/2);
	silk_rline(2*$cw, 0);
	silk_circle($o,$bd/2);
	if ($$r[1] eq "square") {
	    silk_sq($$r[3], 2);
	} else {
	    silk_circle($o,$$r[3]);
	}
	element_stop();
    }
}
#gen_apem_3mek();

sub gen_dil_xx() {
    for (my $poles = 2; $poles <= 30; $poles +=2) {
	my $num = sprintf("%02d", $poles);
	element_start("dil_$num.fp", "# dual in line or column of jumper pins (0.64x0.64mm)\n");

	for (my $ix = 0; $ix < $poles/2; $ix++) {
	    pin( $ix * 2.54 ,  0.00, 1.0, 2.0);
	    pin( $ix * 2.54 , -2.54, 1.0, 2.0);
	}
	silk_bb(0.32);
	element_stop();
    }
}
#gen_dil_xx();

sub gen_harwin_m20() {
    for (my $poles = 2; $poles <= 40; $poles++) {
	my $num = sprintf("%02d", $poles);
	element_start("Harwin_M20_789${num}xx.fp", "# 2.54mm pitch sil pc tail horizontal socket assembly
#http://www.harwin.com/include/downloads/drawings/M20-789.PDF
");

	for (my $ix = 0; $ix < $poles; $ix++) {
	    pin( $ix * 2.54 , -7.87, 0.9, 1.8);
	    use_same_pin_no();
	    pin( $ix * 2.54 ,    0, 0.9, 1.8);
	}
	silk_bb(0.32);
	element_stop();
    }
}
#gen_harwin_m20();

sub gen_harwin_m50() {
    # "Archer"
    my $prefix = "Harwin_M50";
    my $doc_common = "# https://cdn.harwin.com/pdfs/Harwin_Product_Catalog.pdf\n";
    my $pitch = 1.27;

    { # PC Tail/Surfacemount Male Vertical Latching Connectors, i.e. with ejectors
	my $doc = $doc_common . "# page 179\n";
	my $pin_w = [0.40,0.40];
	my $lead_dia = vec_length($pin_w);
	my $drill = lead_to_drill($lead_dia);
	#print "$lead_dia $drill\n";
	$drill = 0.7; # the above gives med 0.8 drill which gives too thin annulus
	$mask_gap  = 0.15;

	my @list = ( 5, 6, 7, 8, 10, 13, 17, 20, 25);
	for my $N (@list) {
	    my @type = (5,6);
	    my $B = 1.27 * ($N - 1);
	    my $A = $B + 15.75;
	    my $C = $B + 8.64;
	    my @body = (6.67, $A);

	    { # pc tail
		my $name = sprintf("%s_3%d%02d", $prefix, $type[0], $N);
		gen_pin_matrix($name, $doc, "y", [$pitch, $pitch], [2, $N], $drill, undef, undef, \&pkg_body_rect, \@body);
	    }
	    { # surface mount
		my $a = 9.04;
		my $px = 4.09;
		my $py = 0.74;
		my $x = (9.04 - $px)/2;
		my $yoffs = ($N-1)/2 * $pitch;
		my $file = sprintf("%s_3%d%02d.fp", $prefix, $type[1], $N);
		element_start($file, $doc);
		for (my $ix = 0; $ix < $N; $ix++) {
		    my $y = $ix * $pitch - $yoffs;
		    pad(-$x, $y, $px, $py);
		    pad($x, $y, $px, $py);
		}
		pkg_body_rect(\@body);
		pr("# locking pegs\n");
		pr("# TODO: check hole dia and position with a real component\n");
		pin(-2.11, -$C/2, 1.9, 2.5, "M1");
		pin(-2.11,  $C/2, 1.9, 2.5, "M1");
		element_stop();
	    }
	}
	$mask_gap  = $mask_gap_default;
    }
    # there are other M50's, but not doing them now
}
#gen_harwin_m50();

sub gen_Hsuan_Mao_C3000() {
    my $doc =
"# http://www1.elfa.se/data1/wwwroot/assets/datasheets/04315305.pdf
# Hsuan Mao Technology co., part no. C3000-XXSLXB00R
";
    my $name = "Hsuan_Mao_C3000";
    my @table = (
	# N = number of pins
	# A = total length of connector
	# B = distance between mounting holes
	# C = distance between first and last column of pins ( = (N/2 - 1)*2.54mm )
	#  N,   A,     B,     C  [mm]
	[ 10, 32.00, 27.94, 10.16 ],
	[ 14, 37.08, 33.02, 15.24 ],
	[ 16, 39.62, 35.56, 17.78 ],
	[ 20, 44.70, 40.64, 22.86 ],
	[ 24, 49.78, 45.72, 27.94 ],
	[ 26, 52.32, 48.26, 30.48 ],
	[ 30, 57.40, 53.34, 35.56 ],
	[ 34, 62.48, 58.42, 40.64 ],
	[ 40, 70.10, 66.04, 48.26 ],
	[ 50, 82.80, 78.74, 60.96 ],
    );
    my $H = 8.20;		# width of connector
    my $W = 4.30;		# width of keying slot in them middle
    my $p = 2.54;		# pitch

    #my $drill = lead_to_drill(0.64,0.64);
    my $drill = 1.1;
    my @thickness = drill2thickness($drill);
    push @thickness, $p - $mask_gap;

    for my $r (@table) {
	my ($N, $A, $B, $C) = @$r;

	$pr_save = "";
	pr_inc();

	pr "# outline\n";
	silk_crect($origin, [$H, $A]);
	pr "# key\n";
	silk_start(-$H/2, -$W/2);
	silk_rline( 1.5, 0);
	silk_rline( 0.0, $W);
	silk_rline(-1.5, 0);
	my $body = $pr_save;
	pr_dec();

	for (my $tx = 0; $tx < @thickness; $tx++) {
	    my $file = sprintf("%s_%02d%s.fp", $name, $N, thickness_suffix($tx));
	    next if ($p < $thickness[$tx] + $mask_gap );

	    element_start($file, $doc);

	    pr "# Mounting holes\n";
	    pin( 0,  $B/2, 2.6, 5.5, 0, "", 0);
	    pin( 0, -$B/2, 2.6, 5.5, 0, "", 0);
	    my $offs = $C/2;
	    for (my $ix = 0; $ix < $N; $ix += 2) {
		my $y = $ix * $p / 2 - $offs;
		pin( -$p/2, $y, $drill, $thickness[$tx]);
		pin(  $p/2, $y, $drill, $thickness[$tx]);
	    }
	    pr($body,1);

	    element_stop();
	}
    }
}
#gen_Hsuan_Mao_C3000();

sub sullings_N($$$$$) {
    my $pitch = shift;
    my $drill = shift;
    my $th = shift;
    my $N = shift; # num pins per row
    my $rows = shift;

    my $x = - $pitch * ($N-1)/2;
    if ($rows == 1) {
	for (my $ix = 0; $ix < $N; $ix++) {
	    pin( $x + $pitch * $ix, 0, $drill, $th);
	}
    } else {
	for (my $ix = 0; $ix < $N; $ix++) {
	    pin( $x + $pitch * $ix,  $pitch/2, $drill, $th);
	    pin( $x + $pitch * $ix, -$pitch/2, $drill, $th);
	}
    }
}
sub gen_sullins_header() {
    # just 2l54 pitch, other pitches are a todo
    my $name = "sullins_header";
    my $doc  = "# https://www.sullinscorp.com/wp-content/uploads/2018/10/2019-CATALOG.pdf\n";
    my $pitchsymbol = "C";
    # male headeers, TODO

    # female headers
    $doc .= "# p.118 - 123\n";
    my @term = qw/ LFB LGB LJB KFX KFM LFH /; # termination styles
    my %mount = (
	LFB => [ qw/ N / ],
	LGB => [ qw/ N / ],
	LJB => [ qw/ N / ],
	KFX => [ qw/ C D / ],
	KFM => [ qw/ S P / ],
	LFH => [ qw/ N / ],
    );
#	qw/ N C D S P /; # mounting styles
    my %dim = (
	#  A==0 -> standing, tail only for smt
	#        A   tail B 1row, 2 rows
	LFB => [ 0  , 0   , 2.54, 5.08 ],
	LGB => [ 8.5, 0   , 2.54, ],
	LJB => [ 8.5, 0   , 0   , 5.08, ],
	KFX => [ 0  , 4.30, 2.50, ],
	KFM => [ 0  , 6.85, 0   , 5.00, ],
	LFH => [ 0  , 0   , 0   , 5.08, ],
    );

    my $pitch = 2.54;
    my $drill = lead_to_drill(0.75, 0.4); # hole mounted
    my $post  = lead_to_drill(1.0); # guide post, mount type S
    my $pinw = 0.54; # SMT
    my @thickness = drill2thickness($drill);
    #print "$drill $post\n";

    # LFB
    for my $term (@term) {
	my $dim = $dim{$term};
	my ($A, $tail, @B) = @$dim;
	my @mount = @{$mount{$term}};
	for my $mount (@mount) {
	    next unless ($mount eq "N");
	    for (my $rx = 0; $rx < @B; $rx++ ) {
		next unless ($B[$rx]);
		my $rows = $rx+1;
		for (my $tx = 0; $tx < @thickness; $tx++) {
		    next if ($pitch < $thickness[$tx] + $mask_gap );
		    my $th = $thickness[$tx];
		    for (my $N = 2; $N <= 40; $N++) {
			my $file = sprintf("%s_xxx%s%02d%1d%s%s-MxxRC_%s.fp",
					   $name, $pitchsymbol, $N, $rows, $term, $mount, thickness_suffix($tx));
			#print "$file\n";
			if ($mount eq "N") {
			    element_start($file, $doc);
			    sullings_N($pitch, $drill, $th, $N, $rows);
			    my $bodyx = ($N-1) * $pitch + 3.04;
			    my $bodyy;
			    if ($A) {
				$bodyy = $A;
			    } else {
				$bodyy = $rows * $pitch;
			    }
			    my @bbw = bb_enlarge($silk_w/2,@bounding_box);
			    if ($term eq "LFB" || $term eq "LFH") {
				# straight up
				silk_crect($origin, [$bodyx,$bodyy], 0, \@bbw);
			    } elsif ($term eq "LGB" || $term eq "LJB") {
				# right angle
				my $offs = 3 + $rx * $pitch/2; # wild guess, TODO
				silk_rect([-$bodyx/2,$offs], [$bodyx/2,$offs+$bodyy], 0, \@bbw);
			    }
			    element_stop();
			} else {
			    # TODO
			}
		    }
		}
	    }
	}
    }
}
#gen_sullins_header();

sub gen_ste_cpm508sq() {
    for (my $poles = 2; $poles <= 24; $poles++) {
	my $num = sprintf("%02d", $poles);
	element_start("stelvio_cpm5.08_${num}sq.fp", "# $poles pole header for pcb
# http://www.stelvio.it/pdf/morsetti.pdf page 50
");
	my $P = 5.08;
	my $X = 3.14;
	my $L = (5.08 * $poles) + 1.2;
	my $ix;

	for ($ix = 0; $ix < $poles; $ix++) {
	    my $x = $P * $ix;
	    pin( $x , 0, 1.4, 3.0);
	    silk_start( $x - 1.8/2, 10);
	    silk_rline( (1.8-1.3)/2, -1.8);
	    silk_rline( 1.3, 0);
	    silk_rline( (1.8-1.3)/2,  1.8);

	}

	silk_start( -$X,  10 );
	silk_rline(   0, -12 );
	silk_rline(  $L,   0 );
	silk_rline(   0,  12 );
	silk_rline( -$L,   0 );

	silk_start( -$X,   7 );
	silk_rline(  $L,   0 );

	pr "\n# make outline for cpf (p.41) which fits in this header\n";
	my $save = $silk_width;
	$silk_width = mk_mm(0.12);

	$X = $P/2;
	$L = $P * $poles;
	silk_start( -$X,  10+10.1);
	silk_rline(   0, -10.1);
	silk_rline(  $L,   0  );
	silk_rline(   0,  10.1);
	silk_rline( -$L,   0  );
	$silk_width = $save;
	element_stop();
    }
}

sub gen_ste_cpm508() {
    for (my $poles = 2; $poles <= 24; $poles++) {
	my $num = sprintf("%02d", $poles);
	element_start("stelvio_cpm5.08_${num}.fp", "# $poles pole header for pcb
# http://www.stelvio.it/pdf/morsetti.pdf page 50
");
	my $P = 5.08;
	my $X = 3.14;
	my $L = (5.08 * $poles) + 1.2;
	my $ix;

	for ($ix = 0; $ix < $poles; $ix++) {
	    my $x = $P * $ix;
	    pin( $x , 0, 1.4, 3.0);
	}

	silk_start( -$X,   3.8 );
	silk_rline(   0, -8.3 );
	silk_rline(  $L,   0 );
	silk_rline(   0,  8.3 );
	silk_rline( -$L,   0 );

	pr "\n# make outline for cpf (p.41) which fits in this header\n";
	my $save = $silk_width;
	$silk_width = mk_mm(0.12);

	$X = $P/2;
	$L = $P * $poles;
	silk_start( -$X,  3.8);
	silk_rline(   0, -15);
	silk_rline(  $L,   0  );
	silk_rline(   0,  15);
	silk_rline( -$L,   0  );
	$silk_width = $save;
	element_stop();
    }
}
#gen_ste_cpm508sq();
#gen_ste_cpm508();

sub gen_phoenix_mkds() {
    my $name = "phoenix_mkds1";
    my $doc =
"# https://docs.rs-online.com/7ed2/A700000008026470.pdf
# https://docs.rs-online.com/511d/A700000008026406.pdf
# https://docs.rs-online.com/c6bb/A700000008026354.pdf
";

    my @pitch = ( 3.5,  3.81);
    my @count = (16  , 13   );
    my @xo    = ( 2.0,  1.9 );
    my $drill = 1.1;
    my @thickness = drill2thickness($drill);
    my $ysz    = 7.3;
    my $yunder = 3.6;
    my $yp    = $ysz / 2 - $yunder;

    for (my $px = 0; $px < @pitch; $px++) {
	my $pitch = $pitch[$px];
	my $count = $count[$px];
	my $xo    = $xo[$px];

	for (my $tx = 0; $tx < @thickness; $tx++) {
	    my $th = $thickness[$tx];
	    for (my $poles = 2; $poles <= $count; $poles++) {
		my $file = sprintf("%s_%02d-%s%s.fp", $name, $poles, $pitch, thickness_suffix($tx));
		next if ($pitch < $thickness[$tx] + $mask_gap );

		my $xw = 2 * $xo + $pitch * ($poles - 1);
		my $x1 = - $pitch * ($poles - 1) / 2;

		element_start($file, $doc);
		for (my $ix = 0; $ix < $poles; $ix++) {
		    pin( $x1 + $ix * $pitch, $yp, $drill, $th);
		}
		silk_rect([ -$xw/2, -$ysz/2 ], [ $xw/2, $ysz/2 ], 0);
		silk_width(0.18);
		silk_start(-$xw/2, $ysz/2 - 0.7);
		silk_rline($xw,0);
		silk_width();
		element_stop();
	    }
	}
    }
}
#gen_phoenix_mkds();

sub multicomp_mtj88fx1() {
    my $name = "multicomp_mtj88fx1";
    my $doc =
"# Modular Telephone Jack, 8P8C Vertical
# /Net/http/www.farnell.com/datasheets/1835945.pdf
# origin between plastic mounts
";
    my $mx = 11.43/2;
    my $my = 0;

    my $px = 1.27;
    my $py = 2.54;
    my $x1 = -8.89/2;
    my $y1 = 8.89 - $py;
    my $drill = 0.9;
    my @thickness = drill2thickness($drill);
    my $spacing = 2.54;

    for (my $tx = 0; $tx < @thickness; $tx++) {
	my $file = sprintf("%s_%s.fp", $name, thickness_suffix($tx));
	my $limit_radius = $thickness[$tx]/2 + $mask_gap;
	if ($spacing/2 < $limit_radius) {
	    #warn "$file: too close spacing <$spacing $limit_radius";
	    next;
	}

	element_start($file,$doc);
	for (my $ix = 0; $ix < 8; ) {
	    pin( $x1 + ($ix++)* $px, -$y1      , $drill, $thickness[$tx]);
	    pin( $x1 + ($ix++)* $px, -$y1 - $py, $drill, $thickness[$tx]);
	}
	pin(  11.43/2, 0, 3.25, 4, "", undef, 0);
	pin( -11.43/2, 0, 3.25, 4, "", undef, 0);

	silk_rect([-15.4/2, 6.25], [15.4/2, 6.25-16.2], 0.5);
	element_stop();
    }
}
#multicomp_mtj88fx1();

sub gen_amphenol_rje392880x00(;$) {
    my $pfx = shift // "AB"; #  pin A1-8,B1-8 with some other prefix

    my $name = "amphenol_rje392880x00";
    my $doc =
"# 2 port high speed modular jack, unshielded
# https://cdn.amphenol-cs.com/media/wysiwyg/files/drawing/rje392880x00.pdf
# origin is midpoint between plastic mounts
";
    my $my = 15.14; # package width
    my $mx = 28.56; # package height
    my $myo = 5.08;  # mount oin to left side

    my $x12 = 1.02; # pin 1-2
    my $x13 = 2.03; # pin 1-3
    my $xPL = 2.06; # pin plug - 116
    my $xss = 14.28; # pin set a to set b
    my $xPP = 25.51; # pin plug - plug

    my $yP1 = -2.54; # plug to pin 1 row
    my $yP2 = -4.32; # plug to pin 2 row

    my $mdrill = 3.25; # plastic mount holes
    my $drill = 0.9;
    my @thickness = drill2thickness($drill);

    # pdf: numbering from right but measured from left
    my $x2 = - $xPP/2 + $xPL + $xss + 3*$x13; # x pos of pin 2
    my $x1 = $x2 + $x12; # x pos of pin 1
    my $x9  = $x1 - $xss;
    my $x10 = $x2 - $xss;

    $round_first_pin = 1;
    for (my $tx = 0; $tx < @thickness; $tx++) {
	my $file = sprintf("%s%s%s.fp", $name, $pfx, thickness_suffix($tx));
	my $limit_radius = $thickness[$tx]/2 + $mask_gap/2;
	if ($x13/2 < $limit_radius) {
	    #warn "$file: too close spacing <$spacing $limit_radius";
	    next;
	}

	element_start($file,$doc, "connector", "X?");

	my $num = substr($pfx,0,1) . "1";
	for (my $ix = 0; $ix < 4; $ix++ ) {
	    pin( $x1 - $ix * $x13, $yP1, $drill, $thickness[$tx], "", "", $num++);
	    pin( $x2 - $ix * $x13, $yP2, $drill, $thickness[$tx], "", "", $num++);
	}
	$num = substr($pfx,1,1) . "1";
	for (my $ix = 0; $ix < 4; $ix++ ) {
	    pin( $x9  - $ix * $x13, $yP1, $drill, $thickness[$tx], "", "", $num++);
	    pin( $x10 - $ix * $x13, $yP2, $drill, $thickness[$tx], "", "", $num++);
	}
	pin( -$xPP/2,  0, $mdrill, $mdrill+0.25, "", "hole", 0);
	pin(  $xPP/2,  0, $mdrill, $mdrill+0.25, "", "hole", 0);

	my @bbw = bb_enlarge($silk_w/2,@bounding_box);
	silk_rect([-$mx/2, $myo], [$mx/2, $myo-$my], 0, \@bbw);
	element_stop();
    }
    $round_first_pin = 0;
}
#gen_amphenol_rje392880x00();
#gen_amphenol_rje392880x00("ED");

sub gen_amp_modular() {
    element_start("amp_modular8_215877.fp", "# AMP Modular jack, side entry, 8 pos
# order number: 215877-1, 1-215877-1, 1-215877-3, or 2-215877-1
# www1.elfa.se/data1/wwwroot/assets/datasheets/04268801.pdf
");
    my $X1 = -8.9;
    my $Y1 = 11.43/2 - 1.27;
    my $ix;

    for ($ix = 0; $ix < 8; ) {
	pin( $X1 + 2.54, $Y1 - ($ix++) * 1.27, 0.9, 2.0);
	pin( $X1       , $Y1 - ($ix++) * 1.27, 0.9, 2.0);
    }
    pin( 0,  11.43/2, 3.25, 3.5);
    pin( 0, -11.43/2, 3.25, 3.5);

    $bbx2 = 7.9;
    $bbx1 = 7.9 - 18.1;
    $bby1 = 15.2/2;
    $bby2 = - $bby1;

    silk_bb(0.32);
    element_stop();
}
#gen_amp_modular();

sub gen_molex_katt_xx() {
    for (my $pairs = 2; $pairs < 5; $pairs++) {
	my $ix;
	my $pitch = 3.78;
	my $pins = 2*$pairs;

	element_start("molex_katt_s${pairs}.fp", "# Molex KATT \"S\" series terminal block
# http://www.farnell.com/datasheets/22056.pdf
");
	for ($ix = 0; $ix < $pins; $ix++) {
	    pin( $pitch * $ix , 0, 0.75, 1.7);
	}

	{
	    my $d = 4.1; # the distance between pin 1 and last pin, when 2 of theese are mounted in a line
	    my $he = 2.5; # the heigth of the ends of the ziczac (y-direction)
	    my $hm = 2.1; # the height of the middle of the ziczac (y-dir)
	    my $wz = 1.0; # the witdh of the ziczac (x-dir)
	    my $ht = 2*$he + $hm;
	    my $wt = $pitch * ($pins - 1) + $d;

	    silk_start( - $d/2 - $wz/2, $ht/2); # start at lower left, near pin 1

	    # left ziczac
	    silk_rline(    0, -$he );
	    silk_rline(  $wz, -$hm );
	    silk_rline(    0, -$he );
	    # top line
	    silk_rline(  $wt,    0 );
	    # right ziczac
	    silk_rline(    0,  $he );
	    silk_rline( -$wz,  $hm );
	    silk_rline(    0,  $he );
	    # bottom line
	    silk_rline( -$wt,    0 );

	    pr "\n# make space for the punch tool\n";
	    my $save = $silk_width;
	    $silk_width = mk_mm(0.12);

	    silk_start( - $d/2 - $wz/2,  15 - 0.8 - $ht/2);
	    silk_rline(              0, -15 );
	    silk_rline(      $wt + $wz,   0 );
	    silk_rline(              0,  15 );
	    silk_rline(    - $wt - $wz,   0 );
	    $silk_width = $save;
	}

	element_stop();
    }
}
#gen molex_katt_xx();

sub gen_ste_mrt9_35() {
    for (my $poles = 2; $poles < 21; $poles++) {
	my $num = sprintf("%02d", $poles);
	element_start("stelvio_mrt9_p3.5_${num}.fp", "# $poles pole header for pcb
# http://www.stelvio.it/pdf/morsetti.pdf page 48
");
	my $P = 3.5;
	my $X = 2.45;
	my $L = (3.5 * $poles) + 1.4;
	my $ix;

	for ($ix = 0; $ix < $poles; $ix++) {
	    pin( 3.5 * $ix , 0, 1.3, 2.3);
	}

	silk_start( -$X,  3   );
	silk_rline(   0, -7.25);
	silk_rline(  $L,  0   );
	silk_rline(   0,  7.25);
	silk_rline( -$L,  0   );

	pr "\n# make outline for mrt8 (p.38) which fits in this header\n";
	my $save = $silk_width;
	$silk_width = mk_mm(0.12);

	$X = 1.75;
	$L = 3.5 * $poles;
	silk_start( -$X,   6.4);
	silk_rline(   0, -11.1);
	silk_rline(  $L,   0  );
	silk_rline(   0,  11.1);
	silk_rline( -$L,   0  );
	$silk_width = $save;
	element_stop();
    }
}
#gen_ste_mrt9_35();

sub gen_ste_mrt9_35sq() {
    for (my $poles = 2; $poles < 21; $poles++) {
	my $num = sprintf("%02d", $poles);
	element_start("stelvio_mrt9_p3.5_${num}sq.fp", "# $poles pole header for pcb
# http://www.stelvio.it/pdf/morsetti.pdf page 48
");
	my $P = 3.5;
	my $X = 2.45;
	my $L = (3.5 * $poles) + 1.4;
	my $ix;

	for ($ix = 0; $ix < $poles; $ix++) {
	    pin( 3.5 * $ix , 0, 1.3, 2.3);
	}

	silk_start( -$X,  8   );
	silk_rline(   0, -9.2 );
	silk_rline(  $L,  0   );
	silk_rline(   0,  9.2 );
	silk_rline( -$L,  0   );

	pr "\n# make outline for mrt8 (p.38) which fits in this header\n";
	my $save = $silk_width;
	$silk_width = mk_mm(0.12);

	$X = 1.75;
	$L = 3.5 * $poles;
	silk_start( -$X,   8  );
	silk_rline(   0,   8.9);
	silk_rline(  $L,   0  );
	silk_rline(   0,  -8.9);
	silk_rline( -$L,   0  );
	$silk_width = $save;
	element_stop();
    }
}
#gen_ste_mrt9_35sq();

sub gen_ste_mrt9_381() {
    for (my $poles = 2; $poles < 21; $poles++) {
	my $num = sprintf("%02d", $poles);
	element_start("stelvio_mrt9_p3.81_${num}.fp", "# $poles pole header for pcb
# http://www.stelvio.it/pdf/morsetti.pdf page 48
");
	my $P = 3.81;
	my $X = 2.6;
	my $L = ($P * $poles) + 1.39;
	my $ix;

	for ($ix = 0; $ix < $poles; $ix++) {
	    pin( $P * $ix , 0, 1.3, 2.3);
	}

	silk_start( -$X,  3   );
	silk_rline(   0, -7.25);
	silk_rline(  $L,  0   );
	silk_rline(   0,  7.25);
	silk_rline( -$L,  0   );

	pr "\n# make outline for mrt8 (p.38) which fits in this header\n";
	my $save = $silk_width;
	$silk_width = mk_mm(0.12);

	$X = 2.3;
	$L = $P * $poles + 0.79;
	silk_start( -$X,   6.4);
	silk_rline(   0, -11.1);
	silk_rline(  $L,   0  );
	silk_rline(   0,  11.1);
	silk_rline( -$L,   0  );
	$silk_width = $save;
	element_stop();
    }
}
#gen_ste_mrt9_381();

sub gen_ste_mrt9_381sq() {
    for (my $poles = 2; $poles < 21; $poles++) {
	my $num = sprintf("%02d", $poles);
	element_start("stelvio_mrt9_p3.81_${num}sq.fp", "# $poles pole header for pcb
# http://www.stelvio.it/pdf/morsetti.pdf page 48
");
	my $P = 3.81;
	my $X = 2.6;
	my $L = ($P * $poles) + 1.39;
	my $ix;

	for ($ix = 0; $ix < $poles; $ix++) {
	    pin( $P * $ix , 0, 1.3, 2.3);
	}

	silk_start( -$X,  8   );
	silk_rline(   0, -9.2 );
	silk_rline(  $L,  0   );
	silk_rline(   0,  9.2 );
	silk_rline( -$L,  0   );

	pr "\n# make outline for mrt8 (p.38) which fits in this header\n";
	my $save = $silk_width;
	$silk_width = mk_mm(0.12);

	$X = 2.3;
	$L = $P * $poles + 0.79;
	silk_start( -$X,   8  );
	silk_rline(   0,   8.9);
	silk_rline(  $L,   0  );
	silk_rline(   0,  -8.9);
	silk_rline( -$L,   0  );
	$silk_width = $save;
	element_stop();
    }
}
#gen_ste_mrt9_381sq();

sub gen_phoenix_ptsa05_xx() {
  my $cnt = 4;
  for ($cnt = 2; $cnt < 13; $cnt++) {
    element_start("phoenix_ptsa05_$cnt.fp", "#
# http://www.farnell.com/datasheets/528306.pdf
");

    # terminals with odd poles start low, even poles start high
    my $up  = 1;
    if ($cnt % 2) {
      $up = 0;
    }

    my $ix;
    my $x = 2.5/2;
    for ($ix = 0; $ix < $cnt; $ix++) {
      my $y;
      if ($up) {
	$y = 0;
	$up = 0;
      } else {
	$y = 5;
	$up = 1;
      }
      pin($x, $y, 1.0, 2.2);
      $x += 2.5;
    }

    pr();
    $bbx1 = -1.5;
    $bbx2 = $cnt * 2.5;
    $bby1 = -2.3;
    $bby2 =  $bby1 + 12;
    silk_bb(0.32);
    element_stop();
  }
}
#gen_phoenix_ptsa05_xx();

sub gen_kyocera_6260() {
    my $name = "kyocera_6260";
    my $doc  = "# https://global.kyocera.com/prdct/electro/product/pdf/6210_6260.pdf\n";
    my $str =
# A = B + 4.8
# B = 0.5 * (N-1)
# C = A + 2 = B + 6.8
# D = B + 1.1
# N  A    B    C    D
"5  6.8  2.0  8.8  3.1
 6  7.3  2.5  9.3  3.6
 7  7.8  3.0  9.8  4.1
 8  8.3  3.5 10.3  4.6
 9  8.8  4.0 10.8  5.1
10  9.3  4.5 11.3  5.6
11  9.8  5.0 11.8  6.1
12 10.3  5.5 12.3  6.6
13 10.8  6.0 12.8  7.1
14 11.3  6.5 13.3  7.6
15 11.8  7.0 13.8  8.1
16 12.3  7.5 14.3  8.6
17 12.8  8.0 14.8  9.1
18 13.3  8.5 15.3  9.6
19 13.8  9.0 15.8 10.1
20 14.3  9.5 16.3 10.6
21 14.8 10.0 16.8 11.1
22 15.3 10.5 17.3 11.6
23 15.8 11.0 17.8 12.1
24 16.3 11.5 18.3 12.6
25 16.8 12.0 18.8 13.1
26 17.3 12.5 19.3 13.6
27 17.8 13.0 19.8 14.1
28 18.3 13.5 20.3 14.6
29 18.8 14.0 20.8 15.1
30 19.3 14.5 21.3 15.6
33 20.8 16.0 22.8 17.1
34 21.3 16.5 23.3 17.6
36 22.3 17.5 24.3 18.6
40 24.3 19.5 26.3 20.6
";
    my $P = 0.5;
    my $px = 0.3;
    my $py = 1.1;
    my @list = split(/[\n\r]+/, $str);
    for (@list) {
	chomp;
	s/^ //;
	my ($N, $A, $B, $C, $D) = split;
	#my @arr = split;
	#my $N = $arr[0];
	#my $B = $P * ($N - 1);
	#my $A = $B + 4.8;
	#my $C = $B + 6.8;
	#my $D = $B + 1.1;
	#if ($A != $arr[1] || $B != $arr[2] || $C != $arr[3] || $D != $arr[4]) { print "$_\n"; }
	for my $r ((0, 0.15)) {
	    my $file;
	    if ($r) {
		$file = sprintf("%s_%02dr.fp", $name, $N);
	    } else {
		$file = sprintf("%s_%02d.fp", $name, $N);
	    }
	    element_start($file, $doc);

	    {
		my $offs = -$B/2;
		my $rr = 0;
		if ($r) { $rr = $px/4; }
		for (my $ix = 0; $ix < $N; $ix++) {
		    my $x = $offs + $ix * $P; # let 0 = connector mid
		    my $y = 0.2 - 1.1/2; # let 0 = housing back side
		    pad($x, $y, $px, $py, "", "", $rr);
		}
	    }
	    {
		pr("\n");
		pr("# Anchor plates\n");
		my $px = 2.1;
		my $py = 1.95;
		# corner nearest signal pads
		my $cx = $B/2 + 3.3 - $px;
		my $cy = 0.2 + 0.4;

		# horiz part
		$py = 1.95 - 0.35;
		my $x = $cx + $px/2;
		my $y = $cy + $py/2;
		pad(-$x, $y, $px, $py, "M1", "", $r, "M1");
		pad( $x, $y, $px, $py, "M2", "", $r, "M2");
		# vertical part
		$px = 2.1 - 0.8;
		$py = 1.95;
		$x = $cx + $px/2;
		$y = $cy + $py/2;
		pad(-$x, $y, $px, $py, "M1", "", $r, "M1");
		pad( $x, $y, $px, $py, "M2", "", $r, "M2");
	    }
	    {
		pr("\n");
		pr("# body outline\n");
		my $body_h = 4.3;
		silk_start($A/2,0);
		silk_rline(0, $body_h-1.1);
		silk_rline(1,0);
		silk_rline(0,0.8);
		silk_arc([$silk_x-0.3,$silk_y],0.3, 180, -90);
		silk_start($C/2-0.3, $body_h);
		silk_line(-$C/2+0.3, $body_h);
		silk_arc([-$C/2+0.3,$body_h-0.3],0.3, 90, -90);
		silk_start(-$C/2, $body_h-0.3);
		silk_rline(0,-0.8);
		silk_rline(1,0);
		silk_rline(0, -$body_h+1.1);
		silk_rline($A,0);
	    }
	    element_stop();
	}
    }
}
#gen_kyocera_6260();

sub gen_Hirose_FH28() {
    my $name = "Hirose_";
    my $doc = "# http://www.farnell.com/datasheets/2691082.pdf\n";

    my @data = (
	# FH28H is space-saving type
	# -0.5SH has 0.5mm pitch
	# -1SH has every odd pin no mounted => 1mm pitch

	#       Part No.        HRS No. #Contacts  A     B      C     D       F    G     H      J
	# Standard type, 0.5mm pitch
	[ qw/ FH28-10S-0.5SH      586-1861-4 10   4.5   9.9   5.57   9.58    5.5   7.1   10.6  7   / ],
	[ qw/ FH28-15S-0.5SH      586-1868-3 15   7    12.4   8.07  12.08    8     9.6   13.1  9.5 / ],
	[ qw/ FH28D-20S-0.5SH     586-1823-5 20   9.5  14.9  10.57  14.58   10.5  12.1  15.6  12.0 / ],
	[ qw/ FH28D-28S-0.5SH     586-1835-4 28  13.5  18.9  14.57  18.58   14.5  16.1  19.6  16.0 / ],
	[ qw/ FH28D-30S-0.5SH     586-1827-6 30  14.5  19.9  15.57  19.58   15.5  17.1  20.6  17.0 / ],
	[ qw/ FH28-40S-0.5SH      586-1803-8 40  19.5  24.9  20.57  24.58   20.5  22.1  25.6  22.0 / ],
	[ qw/ FH28-45S-0.5SH      586-1848-6 45  22    27.4  23.07  27.08   23    24.6  28.1  24.5 / ],
	[ qw/ FH28D-50S-0.5SH     586-1808-1 50  24.5  29.9  25.57  29.58   25.5  27.1  30.6  27.0 / ],
	[ qw/ FH28D-55S-0.5SH     586-1821-0 55  27.0  32.4  28.07  32.08   28.0  29.6  33.1  29.5 / ],
	[ qw/ FH28-60S-0.5SH      586-1811-6 60  29.5  34.9  30.57  34.58   30.5  32.1  35.6  32.0 / ],
	[ qw/ FH28D-64S-0.5SH     586-1813-1 64  31.5  36.9  32.57  36.58   32.5  34.1  37.6  34.0 / ],
	[ qw/ FH28D-68S-0.5SH     586-1819-8 68  33.5  38.9  34.57  38.58   34.5  36.1  39.6  36.0 / ],
	[ qw/ FH28D-74S-0.5SH     586-1828-9 74  36.5  41.9  37.57  41.58   37.5  39.1  42.6  39.0 / ],
	# Space-saving type
	[ qw/ FH28H-80S-0.5SH     586-1805-3 80  39.5  44.9  40.57  45.7    40.5  42.1  46.7  42.0 / ],

	# Standard type, 1mm pitch
	[ qw/ FH28D-20(10)SB-1SH  586-1863-0 10   9    14.9  10.57  14.58   10.5  12.1  15.6  12 / ],
	[ qw/ FH28D-30(15)SB-1SH  586-1860-1 15  14    19.9  15.57  19.58   15.5  17.1  20.6  17 / ],
	[ qw/ FH28-40(20)SB-1SH   586-1832-6 20  19    24.9  20.57  24.58   20.5  22.1  25.6  22 / ],
	[ qw/ FH28D-50(25)SB-1SH  586-1817-2 25  24    29.9  25.57  29.58   25.5  27.1  30.6  27 / ],
	[ qw/ FH28-60(30)SB-1SH   586-1818-5 30  29    34.9  30.57  34.58   30.5  32.1  35.6  32 / ],
	[ qw/ FH28D-64(32)SB-1SH  586-1852-3 32  31    36.9  32.57  36.58   32.5  34.1  37.6  34 / ],
	[ qw/ FH28D-68(34)SB-1SH  586-1812-9 34  33    38.9  34.57  38.58   34.5  36.1  39.6  36 / ],
    );
    #for my $r (@data) {	print join("  ", @$r), "\n"; }

    # difference between space-saving type and standard type is length of actuator
    my $body_w_actuator_ss = 6.0;
    my  ($body_w, $body_w_actuator, $body_top_w, $mnt_pad_l, $pin_stickout) =
	( 5.7,       6.5,              1.9,       1.2,       0.7 );
    my ($pad_x, $pad_y, $pad_skip_std, $mnt_y_std, $pad_skip_ss, $mnt_y_ss) =
	(0.3,   1.3,   3.9,       2.2,      4.2,       1.8);

    # place body so that its mounting "pins" are centered y-wise on the pads
    # use the same offset also for the space saving type
    my $offs_y = -$body_w/2 + 0.1; # body center to bottom of pads

    # cable come from below
    for my $data (@data) {
	#my @fld = @$data;
	my ($part, $hrs, $N, $A, $B, $C, $D, $F, $G, $H, $J) = @$data;
	my $act = $body_w_actuator;
	my $mnt_y = $mnt_y_std;
	my $pad_skip = $pad_skip_std;
	my $pitch = 0.5;

	if ($part =~ m/^FH28H/) {
	    $act = $body_w_actuator_ss;
	    $mnt_y = $mnt_y_ss;
	    $pad_skip = $pad_skip_ss;
	} elsif ($part =~ m/-1SH$/) {
	    $pitch = 1.0;
	    $A += $pitch/2;
	}

	my $file;
	$file = sprintf("%s%s.fp", $name, $part);
	element_start($file, $doc);

	{
	    pr("# Signal pads\n");
	    my $px = $pad_x;
	    my $py = $pad_y;

	    my $x;
	    my $y = $offs_y - $py/2;
	    for (my $ix = 1, $x = -$A/2; $ix <= $N; $ix++, $x += $pitch) {
		pad($x, $y, $px, $py, $ix, "", 0, $ix);
	    }
	}
	{
	    my $px = ($H - $J)/2;
	    my $py = $mnt_y;

	    my $x = ($H + $J)/4;
	    my $y = $offs_y + $pad_skip + $py/2;

	    pr("# Mounting pads\n");
	    pad(-$x, $y, $px, $py, "M1", "", 0, "M1");
	    pad( $x, $y, $px, $py, "M2", "", 0, "M2");
	}
	{
	    pr("\n");
	    pr("# Body\n");
	    my @bbw = bb_enlarge($silk_w/2,@bounding_box);
	    silk_crect($origin, [$B,$body_w], 0, \@bbw);

	}
	{
	    pr("\n");
	    pr("# Incoming cable\n");
	    silk_width(0.12);
	    # J is larger than C so "cable silk" won't overlap with any pad
	    silk_start(-$C/2, -$body_w/2 + $body_top_w);
	    silk_rline( 0, 5);
	    silk_start( $C/2, -$body_w/2 + $body_top_w);
	    silk_rline( 0, 5);
	    silk_width();
	}

	element_stop();
    }
}
#gen_Hirose_FH28();

sub gen_Hirose_FH41() {
    my $name = "Hirose_";
    my $doc = "# http://www.farnell.com/datasheets/2691089.pdf\n"
	. "# http://www.farnell.com/cad/2689896.pdf\n";

    my @data = (
	# Part No.              HRS No.           N   G     C     D     E     F      H       J     K     L
	[ "FH41-15S-0.5SH(05)", "580-2222-2 05", 15,  3,  11.5,  7.0,  5.0,  8.07,  9.45,   9.5,  9.2,  8.0 ],
	[ "FH41-20S-0.5SH(05)", "580-2221-0 05", 20,  4,  14.0,  9.5,  7.5, 10.57, 11.95,  12.0, 11.7, 10.5 ],
	[ "FH41-28S-0.5SH(05)", "580-2208-1 05", 28,  5,  18.0, 13.5, 10.0, 14.57, 15.95,  16.0, 15.7, 14.5 ],
	[ "FH41-30S-0.5SH(05)", "580-2218-5 05", 30,  6,  19.0, 14.5, 12.5, 15.57, 16.95,  17.0, 16.7, 15.5 ],
	[ "FH41-31S-0.5SH(05)", "580-2216-0 05", 31,  6,  19.5, 15.0, 12.5, 16.07, 17.45,  17.5, 17.2, 16.0 ],
	[ "FH41-40S-0.5SH(05)", "580-2205-3 05", 40,  8,  24.0, 19.5, 17.5, 20.57, 21.95,  22.0, 21.7, 20.5 ],
	[ "FH41-50S-0.5SH(28)", "580-2204-0 28", 50, 10,  29.0, 24.5, 22.5, 25.57, 26.95,  27.0, 26.7, 25.5 ],
	[ "FH41-68S-0.5SH(28)", "580-2202-5 28", 68, 13,  38.0, 33.5, 30.0, 34.57, 35.95,  36.0, 35.7, 34.5 ],
    );

    # origo is body center
    my @body = (0, 5.45); # x value to be filled in later
    my @Y = (5.45/2, 5.45/2 - (5.45-5.05), -5.45/2 + 0.6, -5.45/2); # the 0.6 is a guess

    # signal pads
    my $sig_p = 0.5;
    my @sig_pad = (0.3, 0.65);
    my $sig_y = -$body[1]/2 - 0.5 + 0.25/2;

    # ground pads
    my $gnd_p = 2.5;
    my @gnd_pad = (0.3, 1.2);
    my $gnd_y = $body[1]/2 + 0.25 - 0.8/2;

    # mnt pad
    my @mnt_pad = (0.4, 1.55);
    my $mnt_y = $body[1]/2 - 1.15/2;

    # longer than recommended lands, e.g. for handsoldering
    my %ext = ( a => 0, b => 0.5, c => 1.0 );

    for my $k (keys %ext) {
	my $ext = $ext{$k};
	for my $data (@data) {
	    my ($part, $hrs, $N, $G, $C, $D, $E, $F, $H, $J, $K, $L ) = @$data;
	    # ($G - 1) * $P == $E
	    # ($N - 1) * $p == $D
	    # $C - $D = 4.5 / $C - $J = 2 / $J - $D = 2.5
	    # $J - $H = 0.05 / $H - $F = 0.38

	    my $file = sprintf("%s%s_%s.fp", $name, $part, $k);
	    element_start($file, $doc);

	    {
		pr("# Signal pads\n");
		my $x;
		my $y = $sig_y-$ext/2;
		for (my $ix = 1, $x = -$D/2; $ix <= $N; $ix++, $x += $sig_p) {
		    pad($x, $y, $sig_pad[0], $sig_pad[1]+$ext, $ix, "", 0, $ix);
		}
	    }
	    {
		pr("# Ground pads\n");
		my $x;
		my $y = $gnd_y+$ext/2;
		for (my $ix = 1, $x = -$D/2 + 1; $ix <= $G; $ix++, $x += $gnd_p) {
		    pad($x, $y, $gnd_pad[0], $gnd_pad[1]+$ext, "M2", "", 0, "M2");
		}
	    }
	    {
		pr("# Mounting pads\n");
		my $x = $J/2;
		my $y = $mnt_y+$ext/2;
		pad(-$x, $y, $mnt_pad[0], $mnt_pad[1]+$ext, "M1", "", 0, "M1");
		pad( $x, $y, $mnt_pad[0], $mnt_pad[1]+$ext, "M1", "", 0, "M1");
	    }
	    {
		pr("\n");
		pr("# Body\n");
		my @bbw = bb_enlarge($silk_w/2, @bounding_box);

		$body[0] = $C;	# total width
		my $x_top = ($H + $F)/4;

		# clockwise from bottom left of actuator
		silk_start(  - $H/2, $Y[0]);
		silk_line (  - $H/2, $Y[1], \@bbw);
		silk_line (  - $C/2, $Y[1], \@bbw);
		silk_line (  - $C/2, $Y[2]);
		silk_line (- $x_top, $Y[2]);
		silk_line (- $x_top, $Y[3]);

		silk_line (  $x_top, $Y[3], \@bbw); # top of connector

		silk_line (  $x_top, $Y[3]);
		silk_line (  $x_top, $Y[2]);
		silk_line (    $C/2, $Y[2]);
		silk_line (    $C/2, $Y[1], \@bbw);
		silk_line (    $H/2, $Y[1], \@bbw);
		silk_line (    $H/2, $Y[0], \@bbw);

		silk_line (  - $H/2, $Y[0], \@bbw); # bottom of actuator

		pr("\n");
		pr("# Incoming cable\n");
		silk_width(0.12);
		# J is larger than C so "cable silk" won't overlap with any pad
		silk_start(-$F/2, 0);
		silk_rline( 0, 4, \@bbw);
		silk_start( $F/2, 0);
		silk_rline( 0, 4, \@bbw);
		silk_width();
	    }

	    element_stop();
	}
    }

}
#gen_Hirose_FH41();

sub gen_Wuerth_6873xx124422() {
    #my $name = "Wuerth_6873%02d124422";
    my $doc =
"# http://www.farnell.com/cad/2324167.pdf
# https://katalog.we-online.com/en/em/FPC_0_5_SMT_ZIF_VERTICAL_6873XX124422
";

    my @sz = (6,8,10,12,14,16,18,20,22,24,26,28,30,33,34,40,50);
    my $arr = ipc_corner(0.8);
    my $rr  = ipc_corner(0.4);
    for my $N (@sz) {
	my $B = (0.50 * $N) + 6.40;
	my $C = 0.50 * ($N - 1);
	my $D = 0.50 * ($N + 1) + 0.10;
	my $E = $D - 0.10;

	for my $r (("", "r")) {
	    my $file;
	    $file = sprintf("Wuerth_6873%02d124422%s.fp", $N, $r);
	    element_start($file, $doc);

	    my $ix;
	    my $px = 1.5;
	    my $py = 0.4;
	    my $x = (4.3 - $px)/2;
	    my $cr = 0;
	    if ($r) { $cr = $rr; }
	    pr("# signal pads\n");
	    for ($ix = 0; $ix < $N-1; $ix += 2) {
		my $y = -$C/2 + $ix/2 ;
		my $pin = $ix + 1;
		pad(-$x, $y    , $px, $py, $pin, "", $cr, $pin);
		$pin = $ix + 2;
		pad( $x, $y+0.5, $px, $py, $pin, "", $cr, $pin);
	    }
	    if ($ix < $N) {
		my $y = -$C/2 + $ix/2 ;
		my $pin = $ix + 1;
		pad(-$x, $y    , $px, $py, $pin, "", $cr, $pin);
	    }

	    {
		$py = 0.8;
		pr("\n");
		pr("# Anchor plates\n");
		my $y = $C/2 + 1.0;
		my $ar = 0;
		if ($r) { $ar = $arr; }
		pad(-$x,  $y, $px, $py, "M1", "", $ar, "M1");
		pad( $x,  $y, $px, $py, "M1", "", $ar, "M1");
		pad(-$x, -$y, $px, $py, "M2", "", $ar, "M2");
		pad( $x, -$y, $px, $py, "M2", "", $ar, "M2");
	    }
	    {
		pr("\n");
		pr("# body outline\n");
		silk_crect($origin, [2,$B], 0.2);
		my $dx = 1.0;
		silk_width(0.12);
		silk_start(-1.0,-$D/2);
		silk_rline($dx,0);
		silk_rline(0,$D);
		silk_rline(-$dx,0);
		silk_width();
	    }

	    element_stop();
	}
    }
}
#gen_Wuerth_6873xx124422();

sub gen_TE_215079() {
    my $doc = "# http://www.farnell.com/datasheets/1812383.pdf";

    my @sz = ( 4  , 6  ,  8  , 10  , 12  , 14  , 16  , 18  , 20  );
    my @A  = ( 7.1, 9.7, 12.2, 14.7, 17.3, 19.8, 22.4, 24.9, 27.4);
    my $drill = 0.8;
    my @th = drill2thickness($drill);
    my $min_spacing = 2.54;

    for (my $nx = 0; $nx < @sz; $nx++) {
	my $N = $sz[$nx];
	my $A =  $A[$nx];
	my $t = int($N/10);
	my $d = $N - 10*$t;


	$pr_save = "";
	pr_inc();
	pr("\n");
	pr("# body outline\n");
	my $bw = 5.2;
	my $bl = ($N-1) * 1.27 + 2* 1.2; # guess
	my $gap = 2.54;
	my $xbump = ($bw - $gap)/2;
	my $ybump = ($A-$bl)/2;
	silk_start( -$bw/2,   -$A/2);
	silk_rline( $xbump,       0);
	silk_rline(      0,  $ybump);
	silk_rline(   $gap,       0);
	silk_rline(      0, -$ybump);
	silk_rline( $xbump,       0);
	silk_rline(      0,      $A);
	silk_rline(-$xbump,       0);
	silk_rline(      0, -$ybump);
	silk_rline(  -$gap,       0);
	silk_rline(      0,  $ybump);
	silk_rline(-$xbump,       0);
	silk_rline(      0,     -$A);
	pr_dec();
	my $body = $pr_save;

	for (my $tx = 0; $tx < @th; $tx++) {
	    if ($min_spacing < $th[$tx] + $mask_gap) { next; }
	    my $file;
	    if ($t) {
		$file = sprintf( "TE_%d-215079-%d_%s.fp", $t, $d, thickness_suffix($tx));
	    } else {
		$file = sprintf( "TE_215079-%d_%s.fp", $d, thickness_suffix($tx));
	    }

	    element_start($file,$doc);

	    pr("# signal pins\n");
	    my $x = 1.27;
	    my $cc = ($N-1) * 1.27 / 2;
	    my $y;
	    for (my $ix = 0; $ix < $N; $ix += 2) {
		$y = -$cc + $ix * 1.27;
		pin( -$x, $y     , $drill, $th[$tx]);
		pin(  $x, $y+1.27, $drill, $th[$tx]);
	    }
	    pr("\n");
	    pr("# Polarization hole\n");
	    pin( -$x+1.80, -$cc-1.4, 1.5, 1.5);

	    pr($body,1);

	    element_stop();
	}
    }
}
#gen_TE_215079();

sub gen_TycoAMP_1734592() {
    my $name = "TycoAMP_1734592";
    my $doc  = "# http://www.farnell.com/datasheets/586796.pdf\n";

    # origo is in bbox center
    $round_first_pin = 1;

    my $file;
    my @ipc_arr = @{$ipc{"S"}};
    my $cr = 0;
    my $pre;
    my $xoffs;
    my $yoffs;
    my $P = 0.50;
    my $px = 0.3;
    my $py = 1.1;
    my $mx = 2.3;
    my $my = 3.1;
    my $L = 0.5;
    my $ty = 0.7;
    my $lh = 1.45;
    my $th = 4.4;
    my $bh = $th - $lh;

    for (my $ipcx = 1; $ipcx < @ipc_arr; $ipcx++) {
	my $suffix = substr($ipc_hdr[$ipcx], 1, 1);
	my ($toe, $heel, $side, $roundoff, $courtyard) = @{$ipc_arr[$ipcx]};
	my $py = round($L  + $toe + $heel, $roundoff);
	#my $px = round(0.3   + 2*$side     , $roundoff);

	for my $cr ((0, ipc_corner($px))) {
	    for (my $N = 5; $N <= 50; $N++) {
		my $n = $N % 10;
		my $NN = int( $N / 10);
		$NN = $NN ? $NN = "$NN-" : "  ";
		my $partno = "${NN}1734592-$n";
		my $A  = $P * $N + 5.43;
		my $B  = $P * $N + 0.60;
		my $C  = $P * $N - 0.50;
		my $bw = $P * $N + 4.70;
		#printf "%s %2d %5.2f %5.2f %5.2f\n", $partno, $N, $A, $B, $C;
		if ($cr) {
		    $file = sprintf("%s_%02d%sr.fp", $name, $N, $suffix);
		} else {
		    $file = sprintf("%s_%02d%s.fp", $name, $N, $suffix);
		}

		element_start($file, $doc);

		pr("# signal pads\n");
		$yoffs = $th/2 + $ty + $toe - $py/2;
		$xoffs = -($N-1)*$P/2;
		for (my $ix = 0; $ix < $N; $ix++) {
		    my $pin = $ix + 1;
		    pad( $ix * $P + $xoffs, $yoffs, $px, $py, $pin, "", $cr, $pin);
		}

		pr("# mounting pads\n");
		my $inner = $C + 2*2.82 - 2*$mx;
		my $Mx = $mx + $toe - $ipc_gw_LC[0];
		my $pcx = ($inner + $Mx)/2;
		my $pcy = -$th/2 + $lh + $my/2;
		pad( -$pcx, $pcy, $Mx, $my, "M1", "", 0.25, "M1");
		pad(  $pcx, $pcy, $Mx, $my, "M2", "", 0.25, "M2");

		pr("# module outline\n");
		silk_width(0.12);
		silk_rect( [ -$A/2, -$th/2       ], [  +$A/2, -$th/2 + $lh ], 0.2);
		silk_rect( [-$bw/2, -$th/2 + $lh ], [ +$bw/2,  $th/2       ], 0);
		silk_width();
		element_stop();
	    }
	}
    }
    $round_first_pin = 0;
}
#gen_TycoAMP_1734592();

sub gen_jst_SHD() {
    my $name = "jst_shd";
    my $doc =
"# http://www.farnell.com/datasheets/2085439.pdf
# http://www.jst-mfg.com/product/pdf/eng/eSHD.pdf
# http://www.jst-mfg.com/product/detail_e.php?series=232
";
    my @sz = (20, 30, 40, 50);
    my @A  = ( 9, 14, 19, 24);
    my @Bt = ( 12.3, 17.3, 22.3, 27.3 ); # Both Top entry B's
    my @Bs = ( 13.1, 18.1, 23.1, 28.1 ); # Side entry B
    my $fmt_t = "${name}_BM%2dB-SRDS-G-TF%s.fp";   # Top entry type
    my $fmt_s = "${name}_SM%2dB-SRDS-G-TF%s.fp";   # Side entry type
    my $fmt_b = "${name}_BM%2dB-SRDS-A-G-TF%s.fp"; # Top entry type with a boss

    my $pitch = 1;
    my $notch = 0.7; # guess
    my $bw_t = 5.4; # p.1
    my $bw_s = 5.1;
    my $px = 1.6; # signal pads
    my $py = 0.6;
    my $Px = 1.8; # mounting pads
    my $Py = 0.85;
    my $xt = (7.2 - $px)/2;
    my $Xt = -0.5 + $Px/2;
    my $xs = (4.1+$px)/2;
    my $Xs = (4.1 + 2*$px)/2 - 0.9 - $Px/2 ;
    my $file;
    my $Cr  = ipc_corner($py);
    my $mCr = ipc_corner($Py);
    for (my $nx = 0; $nx < @sz; $nx++) {
	my $N = $sz[$nx];
	my $yoffs = - ($N/2 - 1)/2 * $pitch;
	my $Yt = $yoffs - 0.9 - $Py/2;
	my $Ys = $yoffs - 1.25 - $Py/2;
	# both top etnries
	for my $r (("", "r")) {
	    my $cr = 0;
	    my $mcr = 0;
	    if ($r) {
		$cr = $Cr;
		$mcr = $mCr;
	    }
	    for my $boss (("", "boss")) {
		if ($boss) {
		    $file = sprintf($fmt_b, $N, $r);
		} else {
		    $file = sprintf($fmt_t, $N, $r);
		}
		element_start($file, $doc);
		pr("# signal pads\n");
		for (my $ix = 0; $ix < $N/2; $ix++) {
		    my $y = $yoffs + $ix * $pitch;
		    pad( -$xt, $y, $px, $py, 2*$ix+1, "", $cr, 2*$ix+1);
		    pad(  $xt, $y, $px, $py, 2*$ix+2, "", $cr, 2*$ix+2);
		}
		pr("# mounting pads\n");
		pad(  $Xt,  $Yt, $Px, $Py, 0, "", $mcr, 0);
		pad(  $Xt, -$Yt, $Px, $Py, 0, "", $mcr, 0);
		if ($boss) {
		    pr("# boss holes\n");
		    pin( -1.9,  $yoffs - 0.85, 0.55, 0.65, "boss", "", 0);
		    pin( -1.9, -$yoffs + 0.85, 0.55, 0.65, "boss", "", 0);
		}
		pr("# module outline\n");
		silk_crect($origin, [5.4,$Bt[$nx]], [ -0.8,0.3,0.3,0.3 ]);
		element_stop();
	    }

	    # side entry
	    $file = sprintf($fmt_s, $N, $r);
	    element_start($file, $doc);
	    pr("# signal pads\n");
	    for (my $ix = 0; $ix < $N/2; $ix++) {
		my $y = $yoffs + $ix * $pitch;
		pad( -$xs, $y, $px, $py, 2*$ix+1, "", $cr, 2*$ix+1);
		pad(  $xs, $y, $px, $py, 2*$ix+2, "", $cr, 2*$ix+2);
	    }
	    pr("# mounting pads\n");
	    pad(  $Xs,  $Ys, $Px, $Py, "M1", "", $mcr, "M1");
	    pad(  $Xs, -$Ys, $Px, $Py, "M2", "", $mcr, "M2");
	    pr("# module outline\n");
	    silk_crect($origin, [5.1,$Bs[$nx]], 0);
	    silk_width(0.12);
	    silk_crect([5.1/2 + 1, 0], [2,$Bs[$nx]], 0);
	    silk_width();
	    element_stop();
	}
    }

}
#gen_jst_SHD();

sub gen_jst_XSR() {
    my $name = "jst_xsr";
    my $doc =
"# http://www.jst-mfg.com/product/pdf/eng_category/category2/eXSR.pdf
# http://www.jst-mfg.com/product/detail_e.php?series=466
# There is a very small mark for pin #1 on top of the header
";
    my @sz = ( 2, 4, 6, 10, 16, 20, 22 );
    my $fmt_s = "${name}_SM%02dB-XSRS-ETB%s.fp";   # Side entry
    my $fmt_c = "${name}_%02dSR-36S.fp";   # mating cable connector

    # x and y == 0 at body center
    my $Bx = 2; # body width
    my $Bxe = 1; # added width when mating connector is inserted
    my $pitch = 0.6;

    my $Offs_x = 0.15;
    my $Offs_y = 0.6;

    # signal pads
    my $spx = 0.6;
    my $spy = 0.4;
    my $sxc = - $Bx/2 - $Offs_x + 1.6 + $spx/2;

    # mounting pads
    my $mpx = 1.05;
    my $mpy = 0.7;
    my $mxc = - $Bx/2 - $Offs_x + $mpx/2;

    my $file;
    my $Cr  = ipc_corner($spy);
    my $mCr = ipc_corner($mpy);

    my @data = (
	# file name suffix, pad extension, signal pad radius, mounting pad radius
	[ "" , 0  , 0.0, 0.0,   0,    0 ],
	[ "r", 0  , 0.0, 0.0, $Cr, $mCr ],
	[ "y", 0.7, 0.0, 0.7, $Cr, $mCr ],
	[ "x", 0.7, 0.7, 0.0, $Cr, $mCr ],
    );

    for (my $nx = 0; $nx < @sz; $nx++) {
	my $N = $sz[$nx];

	my $A = ($N - 1) * $pitch; # start to end pad center
	my $By = $A + 2.4; # body length

	my $yoffs = - $A/2;
	my $myc = $A/2 + $Offs_y + $mpy/2;

	for my $r (@data) {
	    my ($fn, $ep, $ex, $ey, $cr, $mcr) = @$r;

	    $file = sprintf($fmt_s, $N, $fn);
	    element_start($file, $doc);

	    pr("# signal pads\n");
	    for (my $ix = 0; $ix < $N; $ix++) {
		my $syc = $yoffs + $ix * $pitch;
		pad( $sxc + $ep/2, $syc, $spx + $ep, $spy, $ix+1, "", $cr, $ix+1);
	    }
	    pr("# mounting pads\n");
	    pad(  $mxc - $ex/2,  $myc + $ey/2, $mpx + $ex, $mpy + $ey, "M2", "", $mcr, "M2");
	    pad(  $mxc - $ex/2, -$myc - $ey/2, $mpx + $ex, $mpy + $ey, "M1", "", $mcr, "M1");

	    pr("# body\n");
	    my @bbw = bb_enlarge($silk_w/2,@bounding_box);
	    silk_crect($origin, [$Bx,$By], 0, \@bbw);
	    element_stop();
	}
    }
}
#gen_jst_XSR();

sub gen_jae_FI() {
    my $name = "jae";
    my $doc  =
"# https://www.jae.com/jccom/en/connectors/detail/FI/BoardToCable
# SJ038564.pdf 2-6pin
# SJ100489.pdf 20pin
";
    my $str =
# body is A*w, mated it is A*W
# B = (N-1)* $P
# C = mating conn. width
# D has differint definitions in for diff. N
# px py is signal pas size, lx/ly is mounting lugs, ex/ex is min dis betw. signal pas and mounting pad
# N  A     B     C     D      w    W     px  py   lx  ly    ex    ey
"2  6.1   1.25  3.9   6.4    4.3  7.2   0.7 1.45 1.35 1.6  0.875 2.60
 3  7.35  2.5   5.15  7.65   4.3  7.2   0.7 1.45 1.35 1.6  0.875 2.60
 4  8.6   3.75  6.4   8.9    4.3  7.2   0.7 1.45 1.35 1.6  0.875 2.60
 5  9.85  5.0   7.65 10.15   4.3  7.2   0.7 1.45 1.35 1.6  0.875 2.60
 6 11.1   6.25  8.9  11.4    4.3  7.2   0.7 1.45 1.35 1.6  0.875 2.60
20 28.9  23.75 26.4  30.75   4.25 8.8   0.8 1.70 1.25 2.5  2.475 2.00
";
    my $P = 1.25;
    my @list = split(/[\n\r]+/, $str);
    for (@list) {
	chomp;
	s/^ //;
	my ($N, $A, $B, $C, $D, $w, $W, $px, $py, $lx, $ly, $ex, $ey) = split;
	for my $rr (@radi) {
	    my $radi = 0;
	    my $file = sprintf("%s_FI_S%dP_HFE%s.fp", $name, $N, $rr);
	    element_start($file, $doc);
	    if ($rr) { $radi = ipc_corner($px); }

	    {
		my $offs = $B/2;
		my $y = -$py/2; # let 0 = signal pad end
		for (my $ix = 0; $ix < $N; $ix++) {
		    my $x = $offs - $ix * $P; # let 0 = connector mid
		    pad($x, $y, $px, $py, "", "", $radi);
		}
	    }
	    {
		pr("\n");
		pr("# Anchor plates\n");
		my $r = 0.15;
		my $x = $B/2 + $px/2 + $ex + $lx/2;
		my $y = 0 + $ey + $ly/2;
		pad( $x, $y, $lx, $ly, "M1", "", $radi, "M1");
		pad(-$x, $y, $lx, $ly, "M2", "", $radi, "M2");
	    }
	    {
		pr("\n");
		pr("# body outline\n");
		silk_start($A/2,0);
		silk_rline( 0, $w);
		silk_rline(-$A,0);
		silk_rline( 0, -$w);
		silk_rline( $A,0);

		silk_width(0.12);
		silk_start($C/2,$w);
		silk_line( $C/2,$W);
		silk_rline(-$C,0);
		silk_line(-$C/2,$w);
		silk_width();
	    }
	    element_stop();
	}

    }
}
#gen_jae_FI();

sub gen_molex_47309($) {
    my $add = shift;

    my $name = "molex_47309-xxxx";
    my $doc  =
"# http://www.farnell.com/cad/2199740.pdf
# http://www.farnell.com/datasheets/2199340.pdf
";
    # origo is signal pad end

    my $P = 1.1;
    my $px = 0.6;
    my $py = 1.25 + $add;
    my $N = 8;

    my $file;
    for my $rr (@radi) {
	my $radi = 0;
	if ($rr) { $radi = ipc_corner($px); }
	if ($add) {
	    $file = sprintf("%sw%s.fp", $name, $rr);
	} else {
	    $file = sprintf("%s%s.fp", $name, $rr);
	}
	element_start($file, $doc);
	{
	    my @name = qw| DAT2 CD/DAT3 CMD Vdd CLK Vss DAT0 DAT1 |;
	    my $offs = $P*($N-1)/2;
	    my $y = -$py/2;
	    for (my $ix = 0; $ix < $N; $ix++) {
		my $x = $offs - $ix * $P; # let 0 = connector mid
		my $pin = sprintf( "P%d", $ix + 1);
		pad($x, $y, $px, $py, $name[$ix], "", $radi, $pin);
	    }
	}
	{
	    #my @name = qw| GND GND POL DET |;
	    if ($rr) { $radi = 0.1; }
	    pad(-5.6+1.20/2 -$add/2, -1.95+1.90+3.79/2, 1.20+$add, 3.79, "GND", "", $radi, "G1");
	    pad( 6.2-1.45/2 +$add/2, -1.95+2.35+1.40/2, 1.45+$add, 1.40, "GND", "", $radi, "G2");
	    pad( 6.2-1.00/2 +$add/2, -1.95+4.00+0.60/2, 1.00+$add, 0.60, "POL", "", $radi, "G3");
	    pad( 4.3+0.95/2, -1.95+1.90+3.79 -0.85/2 +$add/2, 0.95, 0.85+$add, "DET", "", $radi, "G4");
	}
	{
	    silk_start(-5.4, -1.95);
	    silk_rline(5.4+6,0);
	    silk_rline(0, 1.91+3.79-0.2);
	    silk_rline(-(5.4+6),0);
	    silk_rline(0, -(1.91+3.79-0.2));

	    silk_width(0.12);
	    silk_start(-4.85, -1.95+1.91+3.79);
	    silk_rline(0, 15.3 - (1.91+3.79));
	    silk_rline(11, 0);
	    silk_rline(0, -(15.3 - (1.91+3.79)));
	    silk_width();
	}
	element_stop();
    }
}
#gen_molex_47309(0);
#gen_molex_47309(0.5);

sub gen_amphenol_GSD0901x(;$$) {
    my $padd = shift // 0; # additioinal pad lenght for non-mounting pins
    my $madd = shift // 0; # additioinal pad lenght for mounting pins


    my $name = "amphenol_GSD0901xSEU";
    my $doc  =
"# http://www.farnell.com/datasheets/2905292.pdf
# http://www.farnell.com/cad/2905309.pdf
";
    # origo is body center
    my $bx = 26.6;
    my $by = 25.0;

    # plastic alignment pins
    my @ad = (1.6, 1.1); # hole dia
    my @ax = (21 - 11.5, -11.5);
    my $ay = -(23 - $by/2);

    my @name = qw| CD/DAT3 CMD VSS1 VDD1 CLK VSS2 DAT0 DAT1 DAT2 CD WP |;

    my @px = ((1.0)x9, (0.7)x2);
    my $py = 1.5;

    my @xc = (0)x11;
    $xc[8] = 9.375;
    $xc[0] = $xc[8] - 2.5;
    for (my $ix = 1; $ix < 7; $ix++) { $xc[$ix] = $xc[$ix-1] - 2.5; }
    $xc[7]  = $xc[6] - 1.7;
    $xc[9]  = $xc[7] - 1.3;
    $xc[10] = $xc[9] - 1.2;
    my $yc  = $ay - 2.05 - $py/2;
    $py += $padd;
    $yc -= $padd/2;

    my $mpx  = 1.5;
    my $mpy  = 2.8;
    my $mxc  = 14.4 - $mpx/2;
    my $mxc2 = $mxc - (28.8-26.6);
    my @myc = ($ay - 2.4 + $mpy/2)x2;
    $myc[1] += 21.5;
    $mpx  += $madd;
    $mxc  += $madd/2;
    $mxc2 += $madd/2;

    {
	$pr_save = "";
	pr_inc();
	{
	    pr("# keep out area\n");
	    silk_width(0.12);
	    silk_rect([-21/2, $ay+10.45-5.30], [21/2, $ay+10.45]);
	    silk_width();
	}
	pr_dec();
    }
    my $body = $pr_save;

    my $file;
    for my $rr (@radi) {
	my $radi = 0;
	if ($padd || $madd) {
	    $file = sprintf("%s%s_%02d%02d.fp", $name, $rr, 10*$padd, 10*$madd);
	} else {
	    $file = sprintf("%s%s.fp", $name, $rr);
	}

 	element_start($file, $doc);

	for (my $ix = 0; $ix < @xc; $ix++) {
	    my $xc = $xc[$ix];
	    my $px = $px[$ix];
	    if ($rr) { $radi = ipc_corner($px); }
	    pad($xc, $yc, $px, $py, $name[$ix], "", $radi, $ix+1);
	}
	{
	    pr("# mounting pads\n");
	    if ($rr) { $radi = ipc_corner($mpx); }
	    pad( -$mxc , $myc[0], $mpx, $mpy, "M1", "", $radi, "M1");
	    pad(  $mxc2, $myc[0], $mpx, $mpy, "M1", "", $radi, "M1");
	    pad( -$mxc , $myc[1], $mpx, $mpy, "M1", "", $radi, "M1");
	    pad(  $mxc , $myc[1], $mpx, $mpy, "M1", "", $radi, "M1");
	}
	pr($body,1);
	my @bbw = bb_sort(@bounding_box);
	@bbw = bb_enlarge($silk_w/2,@bbw);
	pr("# body\n");
	silk_start(-$bx/2, -$by/2);
	silk_rline(0, $by, \@bbw);
	silk_rline($bx, 0, \@bbw);
	silk_rline(0, -17.2, \@bbw);
	silk_rline(25.84-28, -($by-17.2-5), \@bbw);
	silk_rline(0, -5, \@bbw);
	silk_line (-$bx/2, -$by/2, \@bbw);
	element_stop();
    }
}
#gen_amphenol_GSD0901x(0,0);
#gen_amphenol_GSD0901x(1,1);

sub gen_molex_105027($) {
    my $add = shift;

    my $name = "molex_105027_0001";
    my $doc  =
"# http://www.farnell.com/datasheets/2104101.pdf
# http://www.molex.com/pdm_docs/sd/1050270001_sd.pdf
";
    # origo is body center

    my $dx = 0.50;
    my $dy = 1.00 + $add;
    my $gx = 1.05;
    my $gy = 1.20;
    my $bx = 5.75 * 2;
    my $by = 7.16;

    my @name = qw| DAT2 CD/DAT3 CMD Vdd CLK Vss DAT0 DAT1 |;
    my @xpos = ( 3.85, 2.75, 1.65, 0.90, -0.55, -1.65, -2.75, -3.85 );

    my $file;
    for my $rr (@radi) {
	my $radi = 0;
	if ($rr) { $radi = ipc_corner($dx); }
	if ($add) {
	    $file = sprintf("%sw%s.fp", $name, $rr);
	} else {
	    $file = sprintf("%s%s.fp", $name, $rr);
	}
 	element_start($file, $doc);
	my $y = $by/2 - 1.00/2;
	for (my $ix = 0; $ix < @xpos; $ix++) {
	    my $x = $xpos[$ix];
	    my $pin = sprintf( "P%d", $ix + 1);
	    pad($x, $y, $dx, $dy, $name[$ix], "", $radi, $pin);
	}
	pad(0.20, $y, $dx, $dy, "SWITCH", "", $radi, "G1");
	{
	    if ($rr) { $radi = ipc_corner($gx); }
	    pad( -$bx/2+$gx/2 -$add/2, -$by/2+$gx/2-$add/2, $gx+$add, $gy+$add,"M1","",$radi,"M1");
	    pad( -$bx/2+$gx/2 -$add/2,  $by/2-$gx/2+$add/2, $gx+$add, $gy+$add,"M1","",$radi,"M1");
	    pad(  $bx/2-$gx/2 +$add/2, -$by/2+$gx/2-$add/2, $gx+$add, $gy+$add,"M1","",$radi,"M1");
	    pad(  $bx/2-$gx/2 +$add/2,  $by/2-$gx/2+$add/2, $gx+$add, $gy+$add,"M1","",$radi,"M1");
	}
	{
	    my $cy = 15.35-$by;
	    silk_crect($origin,[$bx, $by], 0);

	    silk_width(0.12);
	    silk_start(-4.85, $by/2);
	    silk_rline(0,$cy);
	    silk_rline(11, 0);
	    silk_rline(0,-$cy);
	    silk_rline(-(11-4.85-$bx/2),0);
	    silk_width();
	}
	element_stop();
    }
}
#gen_molex_105027(0);
#gen_molex_105027(0.5);

sub gen_keystone_110_112() {
    my $name = "keystone_110_112";
    my $doc  =
"# keyelco.com 110TR.PDF
# keyelco.com 112TR.PDF
";
    # origo is battery center

    my %battery = ( 20 => 9.4, 23 => 10.9, 24 => 11.4, 30 => 14.4 ); # dia to L
    my @data = (
	[ 3.51, 3.51, 3.96, 3.96, "s" ],
	[ 4, 5, 4, 5, "m" ],
	[ 4, 6, 4, 6, "l" ],
    );
    # if P/N 100/112 are centered on pads, then $cc below is pad center to center dist. diff to L
    my $ccdiff = 3.51/2 + 3.56/2;

    for my $dia (sort keys %battery) {
	my $L = $battery{$dia};
	for my $r (@data) {
	    my ($spx, $spy, $cpx, $cpy, $rr) = @$r;
	    my $cc = $L + $ccdiff;

	    my $radi = 0;
	    if ($rr ne "s") { $radi = ipc_corner($spx); }
	    my $file = sprintf("%s_%2d%s.fp", $name, $dia, $rr);

	    element_start($file, $doc);

	    pad(   0, 0, $cpx, $cpy, "-", "", $radi, 2);
	    pad(-$cc, 0, $spx, $spy, "+", "", $radi, 1);

	    silk_circle([0,0], $dia/2);
	    element_stop();

	}
    }
}
#gen_keystone_110_112();

sub gen_tp() {
    my $y;
    $round_first_pin = 1;

    my @th = drill2thickness(0.9);
    for (my $ix = 0; $ix < @th; $ix++) {
	my $file = sprintf "tp_plainwire_%s.fp", thickness_suffix($ix);
	element_start($file, "# http://www.farnell.com/datasheets/1680152.pdf\n");
	pin( 0, 0, 0.9, $th[$ix]);
	silk_start(0, -1.5);
	silk_rline(0, 3);
	element_stop();
    }

    @th = drill2thickness(1);
    for (my $ix = 0; $ix < @th; $ix++) {
	my $file = sprintf "tp_keystone_5000_%s.fp", thickness_suffix($ix);
	element_start($file,
"# p51/57 keyelco.com/PDF-Catalog-M55/Keystone Catalog M55 v0.2.pdf
# Keystone 5000 .. 5004
# colour keyed th. test point, miniature
");
	pin( 0, 0, 1.0, $th[$ix]);
	silk_circle( [0,0], 2.5/2);
	$y = 1.25 + 2 * 0.25;
	silk_start(0, -$y/2);
	silk_rline(0, $y);
	element_stop();

	$file = sprintf "tp_keystone_5020_%s.fp", thickness_suffix($ix);
	element_start($file,
"# p51/57 keyelco.com/PDF-Catalog-M55/Keystone Catalog M55 v0.2.pdf
# Plain wire th. testpoint, low
");
	pin( 0, 0, 1.0, $th[$ix]);
	$y = 2.5;
	silk_start(0, -$y/2);
	silk_rline(0, $y);
	element_stop();

	$file = sprintf "tp_keystone_5021_%s.fp", thickness_suffix($ix);
	element_start($file,
"# p51/57 keyelco.com/PDF-Catalog-M55/Keystone Catalog M55 v0.2.pdf
# Plain wire th. testpoint, high
");
	pin( 0, 0, 1.0, $th[$ix]);
	$y = 2.4;
	silk_start(0, -$y/2);
	silk_rline(0, $y);
	element_stop();

    }

    @th = drill2thickness(1.6);
    for (my $ix = 0; $ix < @th; $ix++) {
	my $file = sprintf "tp_keystone_5005_%s.fp", thickness_suffix($ix);
	element_start($file,
"# p51/57 keyelco.com/PDF-Catalog-M55/Keystone Catalog M55 v0.2.pdf
# Keystone 5005 .. 5014
# colour keyed th. test point, compact and multipurpose
");
	pin( 0, 0, 1.6, $th[$ix]);
	silk_circle( [0,0], 3.2/2);
	$y = 1.80 + 2 * 0.38;
	silk_start(0, -$y/2);
	silk_rline(0, $y);
	element_stop();
    }

    $round_first_pin = 0;
}
#gen_tp();

sub gen_rpiv3_conn($) {
    my $suffix = shift;
    my $xdoc = "";

    if ($suffix eq "_high") {
	$xdoc = "# high connector, board goes above usb and ethernet connectors, full length\n";
    } elsif ($suffix eq "_low") {
	$xdoc = "# normal connector, board right to ethernet connector with a small margin\n";
    } else {
	return;
    }

    element_start("rpiv3_conn$suffix.fp",
"# Raspberry Pi v2/3 daughter card with mounting holes and 40pin connector
#
# https://www.raspberrypi.org/documentation/hardware/raspberrypi/mechanical/RPI-3B-V1_2.pdf
# http://www.element14.com/community/docs/DOC-73950/l/raspberry-pi-2-model-b-gpio-40-pin-block-pinout
#
# origo i in connector center, which also is the midpoint (x-wise) between mounting holes
$xdoc");

    {
	pr "  # daughter card connector\n";
	my $nn = 40; # 40 pin connector
	my $stax = - $nn/4 * 2.54 + 1.27;
	for (my $ix = 0; $ix < $nn/2; $ix++) {
	    pin( $stax + $ix * 2.54,  1.27, 1.0, 2.0);
	    pin( $stax + $ix * 2.54, -1.27, 1.0, 2.0);
	}
	$bbx1 = -$nn/4 * 2.54;
	$bbx2 =  $nn/4 * 2.54;
	$bby1 = -2.54;
	$bby2 =  2.54;
	silk_bb(0.32);
    }
    {
	pr "  # exteriour\n";
	# board outer dimensions
	my $ox = 85;
	my $oy = 56;
	my $or = 3; # outer corner radius
	my $mb = 3.5; # mounting hole center to card edge

	if ($suffix eq "_low") {
	    $ox = 3.5 + 58 + 3.5;
	}

	my $oleft   = - ( 29 + $mb );
	my $oright  = $oleft + $ox;
	my $otop    = -$mb;
	my $obottom = $otop + $oy;

	# top silk
	silk_start( $oleft  + $or, -$mb);
	silk_line ( $oright - $or, -$mb);
	# right silk
	silk_start( $oright, $otop    + $or);
	silk_line ( $oright, $obottom - $or);
	# bottom silk
	silk_start( $oright - $or, $obottom);
	silk_line ( $oleft  + $or, $obottom);
	# left silk
	silk_start( $oleft, $obottom - $or);
	silk_line ( $oleft, $otop    + $or);

	# outside corners
	silk_arc([ $oleft  + $or, $otop    + $or], $or, 270, 90);
	silk_arc([ $oright - $or, $otop    + $or], $or, 180, 90);
	silk_arc([ $oright - $or, $obottom - $or], $or,  90, 90);
	silk_arc([ $oleft  + $or, $obottom - $or], $or,   0, 90);
    }
    {
	pr "  # mounting holes M2.5\n";
	my $od = 6;
	my $or = $od/2;
	my $id = 2.8;
	my $mount_x = 29;
	my $mount_y = 49;
	#silk_width(0.8);

	$pin_no = 6;
	use_same_pin_no(); pin(-$mount_x,        0, $id, $od);
	use_same_pin_no(); pin( $mount_x,        0, $id, $od);
	use_same_pin_no(); pin( $mount_x, $mount_y, $id, $od);
	use_same_pin_no(); pin(-$mount_x, $mount_y, $id, $od);
    }

    element_stop();
}
#gen_rpiv3_conn("_high");
#gen_rpiv3_conn("_low");

sub gen_eao_series61() {
    my $name = "eao";
    my $doc = "# http://www.eao.com/global/de/Catalogues/PDF_Datei_mit_Zeichnungen/EAO_Baureihen_Empfehlung/EAO-Baureihen-61-Daten.pdf\n";

    my $btl = 0;
    my @art_no = ( "", "61-9820.1", "61-9821.1", "61-9823"); # Bauteilelayout 1, 2, 3
    my $fmt = "# Page 37, art. no %s\n# Page 53, Bauteilelayout %d\n";
    my $drill = 1.0;
    my $cu_dia = drill_to_cudia($drill);
    my $Y = 4.5;
    my $R = 13.1/2; # see p.37 dimensions for 61-9820.1

    {
	$btl++;
	my $file = $name . "_" . $art_no[$btl] . ".fp";
	my $Doc = $doc . sprintf($fmt, $art_no[$btl], $btl);

	element_start($file, $Doc);
	pin( 0,  0 , $drill, $cu_dia);
	pin( 0,  $Y, $drill, $cu_dia);
	silk_circle([0, $Y/2], $R);
	element_stop();
    }

    {
	$btl++;
	my $file = $name . "_" . $art_no[$btl] . ".fp";
	my $Doc = $doc . sprintf($fmt, $art_no[$btl], $btl);
	my $X = 7.62;
	my $dim = [ 23, 15 ];
	my $min = vec_sub( [$X, 1.5*$Y], vec_mul(0.5, $dim));
	my $max = vec_add( $min, $dim);

	element_start($file, $Doc);
	for (my $ix = 0; $ix < 4; $ix++) {
	    pin( 0, $ix * $Y, $drill, $cu_dia);
	}
	pin( $X,   $Y, $drill, $cu_dia);
	pin( $X, 2*$Y, $drill, $cu_dia);
	pin( 2*$X,   $Y, $drill, $cu_dia);
	pin( 2*$X, 2*$Y, $drill, $cu_dia);

	silk_width(0.12);
	silk_circle([$X, 1.5*$Y], $R);
	silk_width();
	silk_rect($min, $max, 0.5);
	element_stop();
    }

    {
	$btl++;
	my $file = $name . "_" . $art_no[$btl] . ".fp";
	my $Doc = $doc . sprintf($fmt, $art_no[$btl], $btl);
	my $X = 13.6/2;
	my $Y2 = 10;
	my $dim = [ 23.6, 17.7 ];
	my $min = vec_sub( [$X, $Y2/2], vec_mul(0.5, $dim));
	my $max = vec_add( $min, $dim);

	element_start($file, $Doc);
	pin(  0,  0 , $drill, $cu_dia);
	pin(  0, $Y2, $drill, $cu_dia);

	pin( $X, $Y2/2 - $Y/2, $drill, $cu_dia);
	pin( $X, $Y2/2 + $Y/2, $drill, $cu_dia);

	pin( 2*$X,  0 , $drill, $cu_dia);
	pin( 2*$X, $Y2, $drill, $cu_dia);

	pin( $X-10, $Y2/2, $drill, $cu_dia); # positioneriung-Loch

	silk_width(0.12);
	silk_circle([$X, $Y2/2], $R);
	silk_width();
	silk_rect($min, $max, 0.5);
	element_stop();
    }
}
#gen_eao_series61();

sub gen_smarc($) {
    my $big = shift; # 0 => small 82x50mm, 1 => big 82x80mm

    my $name = "smarc";
    my $doc = "# p.64 http://www.sget.org/fileadmin/_migrated/content_uploads/SMARC_Hardware_Specification_V1p1.pdf\n";
    my $file;

    for my $rr (@radi) {
	my $radi = 0;
	if ($big) {
	    $file = $name . "_spec82x80$rr.fp";
	} else {
	    $file = $name . "_spec82x50$rr.fp";
	}

	$round_first_pin = 1;
	element_start($file, $doc);

	my $pre;
	my $xoffs;
	my $yoffs;
	my $P = 0.50;
	my $px = 0.3;
	my $py = 2.0;
	if ($rr) { $radi = ipc_corner($px); }

	pr("# primary side pads\n");
	$pre = "P";
	$yoffs = 2.50 + 2.00/2;
	$xoffs = 1.25 - 1*$P;
	for (my $ix = 1; $ix < 75; $ix++) {
	    my $pin = $pre . $ix;
	    pad( $ix * $P + $xoffs, $yoffs, $px, $py, $pin, "", $radi, $pin);
	}
	$xoffs = 40.25 - 75*$P;
	for (my $ix = 75; $ix < 157; $ix++) {
	    my $pin = $pre . $ix;
	    pad( $ix * $P + $xoffs, $yoffs, $px, $py, $pin, "", $radi, $pin);
	}

	pr("# secondary side pads\n");
	$pre = "S";
	$yoffs = -2.50 - 2.00/2;
	$xoffs = 1.00 - 1*$P;
	for (my $ix = 1; $ix < 76; $ix++) {
	    my $pin = $pre . $ix;
	    pad( $ix * $P + $xoffs, $yoffs, $px, $py, $pin, "", $radi, $pin);
	}
	$xoffs = 40.00 - 76*$P;
	for (my $ix = 76; $ix < 159; $ix++) {
	    my $pin = $pre . $ix;
	    pad( $ix * $P + $xoffs, $yoffs, $px, $py, $pin, "", $radi, $pin);
	}

	pr("# mounting pads\n");
	pad( -3.31, 0.98, 3, 5.15, "M1", "", 0.25, "M1");
	pad( 85.31, 0.98, 3, 5.15, "M1", "", 0.25, "M1");

	pr("# mounting holes, hole size depends on mounting gear, this is for M2.5 screw and nut\n");
	pin(  4, -12.13, 2.7, 6.0, "M1", "", "M1");
	pin( 78, -12.13, 2.7, 6.0, "M1", "", "M1");
	pin(  4, -46.13, 2.7, 6.0, "M1", "", "M1");
	pin( 78, -46.13, 2.7, 6.0, "M1", "", "M1");

	if ($big) {
	    pin(  4, -76.13, 2.7, 6.0, "M1", "", "M1");
	    pin( 41, -76.13, 2.7, 6.0, "M1", "", "M1");
	    pin( 78, -76.13, 2.7, 6.0, "M1", "", "M1");
	}

	pr("# centering holes, non electric\n");
	pin(  0,    0, 1.6, 1.6, "M2", "hole", "M2");
	pin( 82,    0, 1.6, 1.6, "M2", "hole", "M2");
	pr("# theese two should be replaced for a 1x1.8mm milled slot\n");
	pin( 39, -0.8, 1.6, 1.6, "M2", "hole", "M2");
	pin( 39,  0.8, 1.6, 1.6, "M2", "hole", "M2");

	pr("# module outline\n");
	my $p1 = [ 0, 0.13 ];
	my $p2;
	if ($big) {
	    $p2 = vec_add($p1, [ 82, -80]);
	} else {
	    $p2 = vec_add($p1, [ 82, -50]);
	}
	#silk_width(0.12);
	silk_rect($p1, $p2, 0);
	silk_width();
	element_stop();
	$round_first_pin = 0;
    }
}
#gen_smarc(0);
#gen_smarc(1);

sub gen_jae_mm70($) {
    my $big = shift; # 0 => small 82x50mm, 1 => big 82x80mm

    # origo is in left (dia 1.6mm) centering hole
    my $name = "jae_mm70";
    my $doc =
"# http://www.jae.com/z-en/pdf_download_exec.cfm?param=SJ109265.pdf
# MB-0207-2E_MM70.pdf
";
    $round_first_pin = 1;

    my $file;
    my $var;
    if ($big) {
	$var = "spec82x80";
    } else {
	$var = "spec82x50";
    }

    my @ipc_arr = @{$ipc{"S"}};
    my $cr = 0;
    my $pre;
    my $xoffs;
    my $yoffs;
    my $P = 0.50;
    my $px = 0.3;
    #my $py = 2.5;
    for (my $ipcx = 1; $ipcx < @ipc_arr; $ipcx++) {
	my $suffix = $ipc_hdr[$ipcx];
	my ($toe, $heel, $side, $roundoff, $courtyard) = @{$ipc_arr[$ipcx]};
	my $py = round(1.5   + $toe + $heel, $roundoff);
	#my $px = round(0.3   + 2*$side     , $roundoff);

	for my $cr ((0, ipc_corner($py))) {
	    if ($cr) {
		$file = sprintf("%s_%s%sr.fp", $name, $var, $suffix);
	    } else {
		$file = sprintf("%s_%s%s.fp", $name, $var, $suffix);
	    }
	    element_start($file, $doc);

	    pr("# primary side pads\n");
	    $pre = "P";
	    $yoffs = 2.25 + $py/2;
	    $xoffs = 1.25 - 1*$P;
	    for (my $ix = 1; $ix < 75; $ix++) {
		my $pin = $pre . $ix;
		pad( $ix * $P + $xoffs, $yoffs, $px, $py, $pin, "", $cr, $pin);
	    }
	    $xoffs = 40.25 - 75*$P;
	    for (my $ix = 75; $ix < 157; $ix++) {
		my $pin = $pre . $ix;
		pad( $ix * $P + $xoffs, $yoffs, $px, $py, $pin, "", $cr, $pin);
	    }

	    pr("# secondary side pads\n");
	    $pre = "S";
	    $yoffs = -4.45 - $py/2;
	    $xoffs = 1.00 - 1*$P;
	    for (my $ix = 1; $ix < 76; $ix++) {
		my $pin = $pre . $ix;
		pad( $ix * $P + $xoffs, $yoffs, $px, $py, $pin, "", $cr, $pin);
	    }
	    $xoffs = 40.00 - 76*$P;
	    for (my $ix = 76; $ix < 159; $ix++) {
		my $pin = $pre . $ix;
		pad( $ix * $P + $xoffs, $yoffs, $px, $py, $pin, "", $cr, $pin);
	    }

	    pr("# mounting pads\n");
	    pad( -1.3 - 3.3/2, -1.10, 3.3, 5.00, "M1", "", 0.25, "M1");
	    pad( 83.3 + 3.3/2, -1.10, 3.3, 5.00, "M1", "", 0.25, "M1");

	    pr("# mounting holes, hole size depends on mounting gear, this is for M2.5 screw and nut\n");
	    pin(  4, -12, 2.7, 6.0, "M1", "", "M1");
	    pin( 78, -12, 2.7, 6.0, "M1", "", "M1");
	    pin(  4, -46, 2.7, 6.0, "M1", "", "M1");
	    pin( 78, -46, 2.7, 6.0, "M1", "", "M1");

	    if ($big) {
		pin(  4, -76, 2.7, 6.0, "M1", "", "M1");
		pin( 41, -76, 2.7, 6.0, "M1", "", "M1");
		pin( 78, -76, 2.7, 6.0, "M1", "", "M1");
	    }

	    pr("# centering holes, non electric\n");
	    pin(  0,    0, 1.6, 1.7, "M2", "", "M2");
	    pin( 82,    0, 1.1, 1.2, "M2", "", "M2");
	    # JAE mm70 doesn't have this hole:
	    #pr("# theese two should be replaced for a 1x1.8mm milled slot\n");
	    #pin( 39, -0.8, 1.6, 1.6, "M2", "hole", "M2");
	    #pin( 39,  0.8, 1.6, 1.6, "M2", "hole", "M2");

	    pr("# module outline\n");
	    my $p1 = [ 0, 0 ];
	    my $p2;
	    if ($big) {
		$p2 = vec_add($p1, [ 82, -80]);
	    } else {
		$p2 = vec_add($p1, [ 82, -50]);
	    }
	    #silk_width(0.12);
	    silk_rect($p1, $p2, 0);
	    silk_width();
	    element_stop();
	}
    }
    $round_first_pin = 0;
}
#gen_jae_mm70(0);
#gen_jae_mm70(1);

sub gen_te_sodimm($) {
    my $volt = shift; # 1.8V or 2.5V, only diff is module size H
    my $name = "te_sodimm";
    my $doc =
"# http://www.farnell.com/cad/2291287.pdf page references it to this pdf
# TE 1473005-4 SOCKET IC, DIMM, DDR2, 1.8V, 200WAY
# free space between module and pcb = 1.9mm (+soldering)
";
    # module pcb centerline heigt over main pcb (p.1 top left dia.) = 3.8
    # module pcb thickness (p.3 top mid) = 1mm
    # module total thickness (p.3 bottom mid left) = 2*1.9mm
    # soo, min free space below module is 3.8 - 1.9 = 1.9mm

    # origo is at the connector mid, see p.2

    $round_first_pin = 1; # no special shape for pad 1
    my $file;

    my $cr = 0;
    my $xoffs;
    my $yoffs;
    my $P = 0.60; # pin pitch
    my $BY = 66.8/2; # boss to boss distance / 2

    # pins are symmetric from boss centerline, p.1 view K-K
    my $pin_len = 0.8;
    my $pin_end = 4.5;
    my $pin_width = 0.15; # top left drawing p.1

    # manufacturer suggested pad size, p.2, have 0.6mm toe and heel, and 0.10mm side
    # the ipc ones (my @ipc_arr = @{$ipc{"S"}};) are smaller, I'll use manuf. ones
    my $py = 0.35;
    my $px = 2.0;
    my $cx = 3.1 + $px/2;
    my $cy; # calc. in loop below

    my $end1 = 40;  # number of pins in sort part (2*20pins), pin 1-40
    my $end2 = 200; # dito. long part, pin 41-200
    my $ysta1 = -$BY + 1.75; # starting y-offset on left side, pin 1
    my $ysta2 = $ysta1 + 4.2 - $P; # dito. pin 41

    my $dsy = 2.7 - 2.4; # or 1.8-1.5, D3 - D4, right to left side y-offset (= $P/2 it seems)

    # mounting pad size and distance/2
    my $mx = 4.6;
    my $my = 4.5;
    my $MY = 60.6/2 + $my/2;

    for my $cr ((0, ipc_corner($py))) {
	my $ix;
	if ($cr) {
	    $file = sprintf("%sr_%.1f.fp", $name, $volt);
	} else {
	    $file = sprintf("%s_%.1f.fp" , $name, $volt);
	}
	element_start($file, $doc);

	pr("# pads 1-40, short part pads\n");
	for ($ix = 0; $ix < $end1; $ix += 2) {
	    my $pin = $ix + 1;
	    pad( -$cx, $ysta1 + $ix     * $P/2, $px, $py, $pin  , "", $cr, $pin  );
	    pad(  $cx, $ysta1 + ($ix+1) * $P/2, $px, $py, $pin+1, "", $cr, $pin+1);
	}

	pr("# pads 41-200, long part pads\n");
	for ( ; $ix < $end2; $ix += 2) {
	    my $pin = $ix + 1;
	    pad( -$cx, $ysta2 + $ix     * $P/2, $px, $py, $pin  , "", $cr, $pin  );
	    pad(  $cx, $ysta2 + ($ix+1) * $P/2, $px, $py, $pin+1, "", $cr, $pin+1);
	}

	pr("# mounting pads\n");
	pad( 12, -$MY, $mx, $my, "M1", "", 0.25, "M1");
	pad( 12,  $MY, $mx, $my, "M1", "", 0.25, "M1");

	pr("# (boss) centering holes, non electric\n");
	pin(  0, -$BY, 1.6, 1.7, "M2", "", "M2");
	pin(  0,  $BY, 1.1, 1.2, "M2", "", "M2");

	pr("# body outline\n");
	silk_width(0.12);
	silk_start(-3.7,-$BY+1.75-$py/2-$mask_gap-0.12/2);
	silk_line( -3.7,-71.1/2+3.2);
	silk_rline(-(5-3.7),0);
	silk_rline(0,-3.2); # manually measured
	silk_rline(5+1.85,0);
	silk_rline(0,71.1);
	silk_rline(-(5+1.85),0);
	silk_rline(0,-3.2); # manually measured
	silk_rline(5-3.7,0);
	silk_line(-3.7, -$BY + 1.75 + 63 + $py/2 + $mask_gap + 0.12/2);

	silk_start(-3.7,-$BY+1.75+11.4+$py/2+$mask_gap+0.12/2);
	silk_rline( 0,4.2-$py-2*$mask_gap-0.12);
	pr("# lock lever/ejector outline\n");
	# top
	silk_start(1.85      , -71.1/2 + 0.8);
	silk_line(13.45-5    , -71.1/2 + 0.8);
	silk_line(13.45-5+1.4, -71.5/2);
	silk_line(21.45-5    , -71.5/2);
	silk_line(26   -5    , -75/2);
	silk_line(26   -5    , -67.9/2);
	# bottom
	silk_start(1.85      ,  71.1/2 - 0.8);
	silk_line(13.45-5    ,  71.1/2 - 0.8);
	silk_line(13.45-5+1.4,  71.5/2);
	silk_line(21.45-5    ,  71.5/2);
	silk_line(26   -5    ,  75/2);
	silk_line(26   -5    ,  67.9/2);
	pr("# module outline\n");
	silk_width(0.07);
	{
	    my %H = (
		1.8 => 31.75,
		2.5 => 25.4,
	    );
	    my $x3 = $H{$volt};
	    my $x1 = 12 - 4.6/2 - $mask_gap - 0.07/2;
	    my $x2 = 12 + 4.6/2 + $mask_gap + 0.07/2;
	    silk_start($x1, -67.96/2);
	    silk_line (  0, -67.96/2);
	    silk_line (  0,  67.96/2);
	    silk_line ($x1,  67.96/2);

	    silk_start($x2, -67.96/2);
	    silk_line ($x3, -67.96/2);
	    silk_line ($x3,  67.96/2);
	    silk_line ($x2,  67.96/2);
	}

	silk_width();
	element_stop();
    }
    $round_first_pin = 0;
}
#gen_te_sodimm(1.8);
#gen_te_sodimm(2.5);

########################################
### MIL connector stuff

sub gen_mil() {
    my $doc = "";

    $doc .= "# https://landandmaritimeapps.dla.mil/Downloads/MilSpec/Docs/MIL-STD-1669/std1669.pdf\n";

    # p.3-4, rotation is clockvice for pins, and counterclockvice for sockets
    my @mil_std_1669_rotation = qw/ W X Y Z /;

    # p.7-62
    # service rating is coded as: 1 = "I", 2 = "II", service rating is "I" unless specified
    # alternate insert positions/rotation, undef = not used position/rotation
    # coordinates in inch (=2.54mm)
    # Note: pcb uses positive Y's down, std has positive Y's up
    # Note: dimensions below are for pins, sockects have the X's mirrored, see 5.1c p.3
    # Note: angles show are negative relative to pcb values
    my %mil_std_1669_pin_arrangement = (
	"8-2" => [       # shell size "-" Arrangement number
	    [ 20, ],     # def. Contact size, def. Service rating
	    [ 58, 122, undef, undef ], # W X Y Z: Alternate insert positions, degrees
	    # contact position, x-coordinate, y-coordinate, size contacts, service rating
	    [ "A", +.059,  .000 ],
	    [ "B", -.059,  .000 ],
	],
	"8-3" => [
	    [ 20, ],
	    [ 60, 210, undef, undef ],
	    [ "A", +.056, +.018 ],
	    [ "B",  .000, -.079 ], # x and y swapped in std
	    [ "C", -.056, +.018 ],
	],
	"8-4" => [
	    [ 20, ],
	    [ 45, undef, undef, undef ],
	    [ "A", -.056, +.056 ],
	    [ "B", -.056, -.056 ],
	    [ "C", +.056, -.056 ],
	    [ "D", +.056, +.056 ],
	],
	"8-33" => [
	    [ 20, ],
	    [ 90, undef, undef, undef ],
	    [ "A",  .000, +.075 ],
	    [ "B", +.065, -.038 ],
	    [ "C", -.065, -.038 ],
	],
	"8-98" => [
	    [ 20, ],
	    [ undef, undef, undef, undef ],
	    [ "A", +.065, +.037 ],
	    [ "B",  .000, -.075 ],
	    [ "C", -.065, +.037 ],
	],
	"10-6" => [
	    [ 20, ],
	    [ 90, undef, undef, undef ],
	    [ "A",  .000, +.130 ],
	    [ "B", +.113, +.065 ],
	    [ "C", +.113, -.065 ],
	    [ "D",  .000, -.130 ],
	    [ "E", -.113, -.065 ],
	    [ "F", -.113, +.065 ],
	],
	"10-98" => [
	    [ 20, ],
	    [ 90, 180, 240, 270 ],
	    [ "A",  .000, +.130 ],
	    [ "B", +.130,  .000 ],
	    [ "C", +.065, -.113 ],
	    [ "D", -.065, -.113 ],
	    [ "E", -.130,  .000 ],
	    [ "F",  .000,  .000 ],
	],
	"12-3" => [
	    [ 16, 2 ],
	    [ undef, undef, 180, undef ],
	    [ "A", +.094, +.058 ],
	    [ "B",  .000, -.111 ],
	    [ "C", -.094, +.058 ],
	],
	"12-8" => [
	    [ 20, ],
	    [ 90, 112, 203, 292 ],
	    [ "A", +.065, +.157 ],
	    [ "B", +.170,  .000 ],
	    [ "C", +.120, -.120 ],
	    [ "D",  .000, -.170 ],
	    [ "E", -.120, -.120 ],
	    [ "F", -.170,  .000 ],
	    [ "G", -.065, +.157 ],
	    [ "H",  .000, +.044 ],
	],
	"12-10" => [
	    [ 20, ],
	    [ 60, 155, 270, 295 ],
	    [ "A",  .000, +.120 ],
	    [ "B", +.130, +.120 ],
	    [ "C", +.195,  .000 ],
	    [ "D", +.130, -.120 ],
	    [ "E",  .000, -.120 ],
	    [ "F", -.130, -.120 ],
	    [ "G", -.195,  .000 ],
	    [ "H", -.130, +.120 ],
	    [ "J", +.065,  .000 ],
	    [ "K", -.065,  .000 ],
	],
	"14-4" => [
	    [ 12, ],
	    [ 45, undef, undef, undef ],
	    [ "A",  .000, +.169 ],
	    [ "B", +.169,  .000 ],
	    [ "C",  .000, -.169 ],
	    [ "D", -.169,  .000 ],
	],
	"14-5" => [
	    [ 16, 2 ],
	    [ 40, 92, 184, 273 ],
	    [ "A", .000, +.100 ],
	    [ "B", +.174, +.024 ],
	    [ "C", +.094, -.148 ],
	    [ "D", -.094, -.148 ],
	    [ "E", -.174, +.024 ],
	],
	"14-9" => [
	    [ 20, ],
	    [ 15, 90, 180, 240 ],
	    [ "A",  .000, +.260 ],
	    [ "B", +.141, +.151, 12 ],
	    [ "C", +.255, +.014 ],
	    [ "D", +.125, -.124, 12 ],
	    [ "E",  .000, -.253 ],
	    [ "F", -.125, -.124, 12 ],
	    [ "G", -.255, +.014 ],
	    [ "H", -.141, +.151, 12 ],
	    [ "J",  .000, +.042 ],
	],
	"14-12" => [
	    [ 20, ],
	    [ 43, 90, undef, undef ],
	    [ "A", +.065, +.243 ],
	    [ "B", +.178, +.178 ],
	    [ "C", +.178, -.178 ],
	    [ "D", +.065, -.243 ],
	    [ "E", -.065, -.243 ],
	    [ "F", -.178, -.178 ],
	    [ "G", -.178, +.178 ],
	    [ "H", -.065, +.243 ],
	    [ "J",  .000, +.094, 16 ],
	    [ "K", +.162,  .000, 16 ],
	    [ "L",  .000, -.094, 16 ],
	    [ "M", -.162,  .000, 16 ],
	],
	"14-15" => [
	    [ 20, ],
	    [ 17, 110, 155, 234 ],
	    [ "A", +.100, +.225 ],
	    [ "B", +.202, +.140 ],
	    [ "C", +.244, +.014 ],
	    [ "D", +.218, -.113 ],
	    [ "E", +.126, -.209 ],
	    [ "F",  .000, -.245 ],
	    [ "G", -.126, -.209 ],
	    [ "H", -.218, -.113 ],
	    [ "J", -.244, +.014 ],
	    [ "K", -.202, +.140 ],
	    [ "L", -.100, +.225 ],
	    [ "M",  .000, +.140 ],
	    [ "N", +.110, +.040 ],
	    [ "P",  .000, -.077 ],
	    [ "R", -.110, +.040, 16 ],
	],
	"14-18" => [
	    [ 20, ],
	    [ 15, 90, 180, 270 ],
	    [ "A", +.065, +.252 ],
	    [ "B", +.195, +.113 ],
	    [ "C", +.260,  .000 ],
	    [ "D", +.195, -.113 ],
	    [ "E", +.130, -.225 ],
	    [ "F",  .000, -.225 ],
	    [ "G", -.130, -.225 ],
	    [ "H", -.195, -.113 ],
	    [ "J", -.260,  .000 ],
	    [ "K", -.195, +.113 ],
	    [ "L", -.065, +.252 ],
	    [ "M", -.065, +.113 ],
	    [ "N", +.065, +.113 ],
	    [ "P", +.130,  .000 ],
	    [ "R", +.065, -.113 ],
	    [ "S", -.065, -.113 ],
	    [ "T", -.130,  .000 ],
	    [ "U",  .000,  .000 ],
	],
	"14-19" => [
	    [ 20, ],
	    [ 30, 165, 315, undef ],
	    [ "A",  .000, +.225 ],
	    [ "B", +.130, +.225 ],
	    [ "C", +.195, +.113 ],
	    [ "D", +.260,  .000 ],
	    [ "E", +.195, -.113 ],
	    [ "F", +.130, -.225 ],
	    [ "G",  .000, -.225 ],
	    [ "H", -.130, -.225 ],
	    [ "J", -.195, -.113 ],
	    [ "K", -.260,  .000 ],
	    [ "L", -.195, +.113 ],
	    [ "M", -.130, +.225 ],
	    [ "N", -.065, +.113 ],
	    [ "P", +.065, +.113 ],
	    [ "R", +.130,  .000 ],
	    [ "S", +.065, -.113 ],
	    [ "T", -.065, -.113 ],
	    [ "U", -.130,  .000 ],
	    [ "V",  .000,  .000 ],
	],
	"14-22" => [
	    [ 12, ],
	    [ 45, undef, undef, undef ],
	    [ "A",  .000, +.191 ],
	    [ "B", -.191,  .000 ],
	    [ "C",  .000, -.191 ],
	    [ "D", +.191,  .000 ],
	    [ "E",  .000,  .000, 20 ],
	],
	"16-8" => [
	    [ 16, 2 ],
	    [ 54, 152, 180, 331 ],
	    [ "A",  .000, +.236 ],
	    [ "B", +.128, +.086 ],
	    [ "C", +.230, -.078 ],
	    [ "D", +.094, -.216 ],
	    [ "E", -.094, -.216 ],
	    [ "F", -.230, -.078 ],
	    [ "G", -.128, +.086 ],
	    [ "H",  .000, -.052 ],
	],
	"16-14" => [
	    [ 20, ],
	    [ 25, 78, 180, 240 ],
	    [ "A",  .000, +.268 ],
	    [ "B", +.178, +.266 ],
	    [ "C", +.268, +.173 ],
	    [ "D", +.268, -.005 ],
	    [ "E", +.165, -.212 ],
	    [ "F",  .000, -.320 ],
	    [ "G", -.165, -.212 ],
	    [ "H", -.268, -.005 ],
	    [ "J", -.268, +.173 ],
	    [ "K", -.178, +.266 ],
	    [ "L", +.142, +.139 ],
	    [ "M",  .000, -.146 ],
	    [ "N", -.142, +.139 ],
	    [ "P",  .000, +.032 ],
	],
	"16-23" => [
	    [ 20, ],
	    [ 158, 270, undef, undef ],
	    [ "A", +.070, +.300 ],
	    [ "B", +.193, +.240 ],
	    [ "C", +.278, +.134 ],
	    [ "D", +.308,  .000 ],
	    [ "E", +.278, -.134 ],
	    [ "F", +.193, -.240 ],
	    [ "G", +.070, -.300 ],
	    [ "H", -.070, -.300 ],
	    [ "J", -.193, -.240 ],
	    [ "K", -.278, -.134 ],
	    [ "L", -.308,  .000 ],
	    [ "M", -.278, +.134 ],
	    [ "N", -.193, +.240 ],
	    [ "P", -.070, +.300 ],
	    [ "R",  .000, +.178 ],
	    [ "S", +.126, +.126 ],
	    [ "T", +.178,  .000 ],
	    [ "U", +.126, -.126 ],
	    [ "V",  .000, -.178 ],
	    [ "W", -.126, -.126 ],
	    [ "X", -.178,  .000 ],
	    [ "Y", -.126, +.126 ],
	    [ "Z",  .000,  .000 ],
	],
	"16-26" => [
	    [ 20, ],
	    [ 60, undef, 275, 338 ],
	    [ "A",  .000, +.321 ],
	    [ "B", +.131, +.293 ],
	    [ "C", +.239, +.214 ],
	    [ "D", +.305, +.099 ],
	    [ "E", +.319, -.034 ],
	    [ "F", +.278, -.161 ],
	    [ "G", +.189, -.260 ],
	    [ "H", +.067, -.314 ],
	    [ "J", -.067, -.314 ],
	    [ "K", -.189, -.260 ],
	    [ "L", -.278, -.161 ],
	    [ "M", -.319, -.034 ],
	    [ "N", -.305, +.099 ],
	    [ "P", -.239, +.214 ],
	    [ "R", -.131, +.293 ],
	    [ "S", -.070, +.177 ],
	    [ "T", +.070, +.177 ],
	    [ "U", +.175, +.094 ],
	    [ "V", +.178, -.036 ],
	    [ "W", +.119, -.151 ],
	    [ "X",  .000, -.203 ],
	    [ "Y", -.119, -.151 ],
	    [ "Z", -.178, -.036 ],
	    [ "a", -.175, +.094 ],
	    [ "b",  .000, +.065 ],
	    [ "c",  .000, -.065 ],
	],
	"16-95" => [
	    [ 20, ],
	    [ 25, 90, 153, undef ],
	    [ "A",  .000, +.162 ],
	    [ "B", +.115, +.261 ],
	    [ "C", +.200,  .000, 2 ],
	    [ "D", +.143, -.250 ],
	    [ "E",  .000, -.162 ],
	    [ "F", -.143, -.250 ],
	    [ "G", -.200,  .000, 2 ],
	    [ "H", -.115, +.261 ],
	],
	"16-99" => [
	    [ 20, ],
	    [ 66, 156, 223, 340 ],
	    [ "A",  .000, +.321 ],
	    [ "B", +.131, +.293 ],
	    [ "C", +.239, +.214 ],
	    [ "D", +.305, +.099 ],
	    [ "E", +.319, -.034 ],
	    [ "F", +.278, -.161 ],
	    [ "G", +.189, -.260 ],
	    [ "H", +.067, -.314 ],
	    [ "J", -.067, -.314 ],
	    [ "K", -.189, -.260 ],
	    [ "L", -.278, -.161 ],
	    [ "M", -.319, -.034 ],
	    [ "N", -.305, +.099 ],
	    [ "P", -.239, +.214 ],
	    [ "R", -.131, +.293 ],
	    [ "S", -.070, +.177 ],
	    [ "T", +.070, +.177 ],
	    [ "U", +.175, +.094 ],
	    [ "V", +.150, -.075 ],
	    [ "W",  .000, -.161, 16 ],
	    [ "X", -.150, -.075 ],
	    [ "Y", -.175, +.094 ],
	    [ "Z",  .000, +.025, 16 ],
	],
	"18-8" => [
	    [ 12, ],
	    [ 180, undef, undef, undef ],
	    [ "A", .000, +.280 ],
	    [ "B", +.219, +.175 ],
	    [ "C", +.273, -.062 ],
	    [ "D", +.121, -.252 ],
	    [ "E", -.121, -.252 ],
	    [ "F", -.273, -.062 ],
	    [ "G", -.219, +.175 ],
	    [ "H", .000, .000 ],
	],
	"18-11" => [
	    [ 16, 2 ],
	    [ 62, 119, 241, 340 ],
	    [ "A", +.105, +.260 ],
	    [ "B", +.250, +.132 ],
	    [ "C", +.275, -.053 ],
	    [ "D", +.179, -.215 ],
	    [ "E",  .000, -.281 ],
	    [ "F", -.179, -.215 ],
	    [ "G", -.275, -.053 ],
	    [ "H", -.250, +.132 ],
	    [ "J", -.105, +.260 ],
	    [ "K",  .000, +.105 ],
	    [ "L",  .000, -.092 ],
	],
	"18-30" => [
	    [ 20, ],
	    [ 180, 193, 285, 350 ],
	    [ "A", +.065, +.346 ],
	    [ "B", +.186, +.299 ],
	    [ "C", +.282, +.210 ],
	    [ "D", +.340, +.093 ],
	    [ "E", +.351, -.033 ],
	    [ "F", +.315, -.158 ],
	    [ "G", +.236, -.261 ],
	    [ "H", +.124, -.330 ],
	    [ "J", -.124, -.330 ],
	    [ "K", -.236, -.261 ],
	    [ "L", -.315, -.158 ],
	    [ "M", -.351, -.033 ],
	    [ "N", -.340, +.093 ],
	    [ "P", -.282, +.210 ],
	    [ "R", -.186, +.299 ],
	    [ "S", -.065, +.346 ],
	    [ "T", +.084, +.217 ],
	    [ "U", +.181, +.129 ],
	    [ "V", +.228, +.008 ],
	    [ "W", +.193, -.117 ],
	    [ "X", +.096, -.203 ],
	    [ "Y",  .000, -.290 ],
	    [ "Z", -.096, -.203 ],
	    [ "a", -.193, -.117 ],
	    [ "b", -.228, +.008 ],
	    [ "c", -.181, +.129 ],
	    [ "d", -.084, +.217 ],
	    [ "e",  .000, +.072 ],
	    [ "f", +.069, -.076 ],
	    [ "g", -.069, -.076 ],
	],
	"18-32" => [
	    [ 20, ],
	    [ 85, 138, 222, 265 ],
	    [ "A", +.066, +.353 ],
	    [ "B", +.189, +.305 ],
	    [ "C", +.286, +.217 ],
	    [ "D", +.345, +.098 ],
	    [ "E", +.357, -.033 ],
	    [ "F", +.321, -.160 ],
	    [ "G", +.242, -.265 ],
	    [ "H", +.130, -.335 ],
	    [ "J",  .000, -.359 ],
	    [ "K", -.130, -.335 ],
	    [ "L", -.242, -.265 ],
	    [ "M", -.321, -.160 ],
	    [ "N", -.357, -.033 ],
	    [ "P", -.345, +.098 ],
	    [ "R", -.286, +.217 ],
	    [ "S", -.189, +.305 ],
	    [ "T", -.066, +.353 ],
	    [ "U",  .000, +.230 ],
	    [ "V", +.124, +.193 ],
	    [ "W", +.209, +.095 ],
	    [ "X", +.228, -.033 ],
	    [ "Y", +.174, -.151 ],
	    [ "Z", +.065, -.221 ],
	    [ "a", -.065, -.221 ],
	    [ "b", -.174, -.151 ],
	    [ "c", -.228, -.033 ],
	    [ "d", -.209, +.095 ],
	    [ "e", -.124, +.193 ],
	    [ "f",  .000, +.096 ],
	    [ "g", +.096,  .000 ],
	    [ "h",  .000, -.096 ],
	    [ "j", -.096,  .000 ],
	],
	"18-85" => [
	    [ 12, ],
	    [ 45, 90, 180, 240 ],
	    [ "A",  .000, +.305 ],
	    [ "B", +.215, +.215 ],
	    [ "C", +.305,  .000 ],
	    [ "D", +.215, -.214 ],
	    [ "E",  .000, -.300 ],
	    [ "F", -.215, -.214 ],
	    [ "G", -.305,  .000 ],
	    [ "H", -.215, +.215 ],
	    [ "J",  .000, +.122, 20 ],
	    [ "K", +.126, +.059, 20 ],
	    [ "L", +.078, -.079, 20 ],
	    [ "M", -.078, -.079, 20 ],
	    [ "N", -.126, +.059, 20 ],
	],
	"18-88" => [
	    [ 20, ],
	    [ 12, 45, 168, 202 ],
	    [ "A",  .000, +.350 ],
	    [ "B", +.175, +.175, 8 ],
	    [ "C", +.350,  .000 ],
	    [ "D", +.175, -.175, 8 ],
	    [ "E", -.175, -.175, 8 ],
	    [ "F", -.350,  .000 ],
	    [ "G", -.175, +.175, 8 ],
	    [ "H",  .000,  .000 ],
	],
	"20-16" => [
	    [ 16, 2 ],
	    [ 238, 318, 333, 347 ],
	    [ "A", +.118, +.322 ],
	    [ "B", +.271, +.211 ],
	    [ "C", +.341, +.036 ],
	    [ "D", +.308, -.150 ],
	    [ "E", +.182, -.290 ],
	    [ "F",  .000, -.343 ],
	    [ "G", -.182, -.290 ],
	    [ "H", -.308, -.150 ],
	    [ "J", -.341, +.036 ],
	    [ "K", -.271, +.211 ],
	    [ "L", -.118, +.322 ],
	    [ "M",  .000, +.175 ],
	    [ "N", +.154, +.062 ],
	    [ "P", +.094, -.122 ],
	    [ "R", -.094, -.122 ],
	    [ "S", -.154, +.062 ],
	],
	"20-24" => [
	    [ 20, ],
	    [ 70, 145, 215, 290 ],
	    [ "A", +.175, +.375 ],
	    [ "B", +.350, +.200 ],
	    [ "C", +.400,  .000 ],
	    [ "D", +.350, -.200 ],
	    [ "E", +.200, -.350 ],
	    [ "F",  .000, -.400 ],
	    [ "G", -.200, -.350 ],
	    [ "H", -.350, -.200 ],
	    [ "J", -.400,  .000 ],
	    [ "K", -.350, +.200 ],
	    [ "L", -.175, +.375 ],
	    [ "M",  .000, +.300 ],
	    [ "N", +.150, +.200 ],
	    [ "P", +.250,  .000 ],
	    [ "R", +.200, -.150 ],
	    [ "S", +.075, -.250 ],
	    [ "T", -.075, -.250 ],
	    [ "U", -.200, -.150 ],
	    [ "V", -.250,  .000 ],
	    [ "W", -.150, +.200 ],
	    [ "X",  .000, +.150 ],
	    [ "Y", +.100, +.025 ],
	    [ "Z",  .000, -.100 ],
	    [ "a", -.100, +.025 ],
	],
	"20-27" => [
	    [ 20, ],
	    [ 72, 144, 216, 288 ],
	    [ "A",  .000, +.400 ],
	    [ "B", +.150, +.375 ],
	    [ "C", +.275, +.275 ],
	    [ "D", +.375, +.150 ],
	    [ "E", +.400,  .000 ],
	    [ "F", +.375, -.150 ],
	    [ "G", +.275, -.300 ],
	    [ "H", +.100, -.400 ],
	    [ "J", -.100, -.400 ],
	    [ "K", -.275, -.300 ],
	    [ "L", -.375, -.150 ],
	    [ "M", -.400,  .000 ],
	    [ "N", -.375, +.150 ],
	    [ "P", -.275, +.275 ],
	    [ "R", -.150, +.375 ],
	    [ "S", +.125, +.225 ],
	    [ "T", +.225, -.100 ],
	    [ "U", +.250, -.050 ],
	    [ "V", +.150, -.200 ],
	    [ "W",  .000, -.250 ],
	    [ "X", -.150, -.200 ],
	    [ "Y", -.250, -.050 ],
	    [ "Z", -.225, -.100 ],
	    [ "a", -.125, +.225 ],
	    [ "b",  .000, +.100 ],
	    [ "c", +.100, -.025 ],
	    [ "d", -.100, -.025 ],
	],
	"20-39" => [
	    [ 20, ],
	    [ 63, 144, 252, 333 ],
	    [ "A", +.065, +.411 ],
	    [ "B", +.189, +.371 ],
	    [ "C", +.294, +.294 ],
	    [ "D", +.371, +.189 ],
	    [ "E", +.411, +.065 ],
	    [ "F", +.411, -.065 ],
	    [ "G", +.371, -.189 ],
	    [ "H", +.294, -.294 ],
	    [ "J", +.189, -.371 ],
	    [ "K", +.065, -.411 ],
	    [ "L", -.065, -.411 ],
	    [ "M", -.189, -.371 ],
	    [ "N", -.294, -.294 ],
	    [ "P", -.371, -.189 ],
	    [ "R", -.411, -.065 ],
	    [ "S", -.411, +.065 ],
	    [ "T", -.371, +.189 ],
	    [ "U", -.294, +.294 ],
	    [ "V", -.189, +.371 ],
	    [ "W", -.065, +.411 ],
	    [ "X",  .000, +.295 ],
	    [ "Y", +.126, +.256 ],
	    [ "Z", +.232, +.179 ],
	    [ "a", +.280, +.057 ],
	    [ "b", +.280, -.074 ],
	    [ "c", +.217, -.189 ],
	    [ "d", +.112, -.265 ],
	    [ "e", -.112, -.265 ],
	    [ "f", -.217, -.189 ],
	    [ "g", -.280, -.074 ],
	    [ "h", -.280, +.057 ],
	    [ "i", -.232, +.179 ],
	    [ "j", -.126, +.256 ],
	    [ "k",  .000, +.164 ],
	    [ "m", +.114, +.048 ],
	    [ "n", +.106, -.107 ],
	    [ "p",  .000, +.189 ],
	    [ "q", -.106, -.107 ],
	    [ "r", -.114, +.048 ],
	],
	"20-41" => [
	    [ 20, ],
	    [ 45, 126, 225, undef ],
	    [ "A",  .000, +.418 ],
	    [ "B", +.129, +.397 ],
	    [ "C", +.245, +.338 ],
	    [ "D", +.338, +.245 ],
	    [ "E", +.397, +.129 ],
	    [ "F", +.418,  .000 ],
	    [ "G", +.397, -.129 ],
	    [ "H", +.338, -.245 ],
	    [ "J", +.245, -.338 ],
	    [ "K", +.129, -.397 ],
	    [ "L",  .000, -.418 ],
	    [ "M", -.129, -.397 ],
	    [ "N", -.245, -.338 ],
	    [ "P", -.338, -.245 ],
	    [ "R", -.397, -.129 ],
	    [ "S", -.418,  .000 ],
	    [ "T", -.397, +.129 ],
	    [ "U", -.338, +.245 ],
	    [ "V", -.245, +.338 ],
	    [ "W", -.129, +.397 ],
	    [ "X",  .000, +.284 ],
	    [ "Y", +.132, +.251 ],
	    [ "Z", +.233, +.161 ],
	    [ "a", +.281, +.034 ],
	    [ "b", +.265, -.101 ],
	    [ "c", +.188, -.212 ],
	    [ "d", +.068, -.275 ],
	    [ "e", -.068, -.275 ],
	    [ "f", -.188, -.212 ],
	    [ "g", -.265, -.101 ],
	    [ "h", -.281, +.034 ],
	    [ "i", -.233, +.161 ],
	    [ "j", -.132, +.251 ],
	    [ "k",  .000, +.150 ],
	    [ "m", +.117, +.094 ],
	    [ "n", +.146, -.033 ],
	    [ "p", +.065, -.135 ],
	    [ "q", -.065, -.135 ],
	    [ "r", -.146, -.033 ],
	    [ "s", -.117, +.094 ],
	    [ "t",  .000,  .000 ],
	],
	"20-90" => [
	    [ 12, ],
	    [ 18, 60, 240, 270 ],
	    [ "A",  .000, +.368 ],
	    [ "B", +.224, +.292 ],
	    [ "C", +.356, +.095 ],
	    [ "D", +.341, -.142 ],
	    [ "E", +.182, -.319 ],
	    [ "F",  .000, -.368 ],
	    [ "G", -.182, -.319 ],
	    [ "H", -.341, -.142 ],
	    [ "J", -.356, +.095 ],
	    [ "K", -.224, +.292 ],
	    [ "L", +.120, +.079 ],
	    [ "M", +.166, -.098 ],
	    [ "N",  .000, -.170 ],
	    [ "P", -.166, -.098 ],
	    [ "R", -.120, +.079 ],
	],
	"22-12" => [
	    [ 12, ],
	    [ undef, undef, undef, undef ],
	    [ "A",  .000, +.398 ],
	    [ "B", +.256, +.305 ],
	    [ "C", +.392, +.069 ],
	    [ "D", +.345, -.199 ],
	    [ "E", +.136, -.374 ],
	    [ "F", -.136, -.374 ],
	    [ "G", -.345, -.199 ],
	    [ "H", -.392, +.069 ],
	    [ "J", -.256, +.305 ],
	    [ "K", +.131, +.075 ],
	    [ "L",  .000, -.151 ],
	    [ "M", -.131, +.075 ],
	],
	"22-19" => [
	    [ 12, ],
	    [ 15, 90, 225, 308 ],
	    [ "A", +.114, +.425 ],
	    [ "B", +.311, +.311 ],
	    [ "C", +.425, +.114 ],
	    [ "D", +.425, -.114 ],
	    [ "E", +.311, -.311 ],
	    [ "F", +.114, -.425 ],
	    [ "G", -.114, -.425 ],
	    [ "H", -.311, -.311 ],
	    [ "J", -.425, -.114 ],
	    [ "K", -.425, +.114 ],
	    [ "L", -.311, +.311 ],
	    [ "M", -.114, +.425 ],
	    [ "N",  .000, +.228 ],
	    [ "P", +.197, +.114 ],
	    [ "R", +.197, -.114 ],
	    [ "S",  .000, -.228 ],
	    [ "T", -.197, -.114 ],
	    [ "U", -.197, +.114 ],
	    [ "V",  .000,  .000 ],
	],
	"22-21" => [
	    [ 16, 2 ],
	    [ 16, 135, 175, 349 ],
	    [ "A", +.128, +.385 ],
	    [ "B", +.289, +.285 ],
	    [ "C", +.386, +.123 ],
	    [ "D", +.400, -.065 ],
	    [ "E", +.328, -.239 ],
	    [ "F", +.183, -.362 ],
	    [ "G",  .000, -.406 ],
	    [ "H", -.183, -.362 ],
	    [ "J", -.328, -.239 ],
	    [ "K", -.400, -.065 ],
	    [ "L", -.386, +.123 ],
	    [ "M", -.289, +.285 ],
	    [ "N", -.128, +.385 ],
	    [ "P",  .000, +.245 ],
	    [ "R", +.160, +.146 ],
	    [ "S", +.214, -.035 ],
	    [ "T", +.094, -.194 ],
	    [ "U", -.094, -.194 ],
	    [ "V", -.214, -.035 ],
	    [ "W", -.160, +.146 ],
	    [ "X",  .000 , .000 ],
	],
	"22-32" => [
	    [ 20, ],
	    [ 72, 145, 215, 288 ],
	    [ "A", +.100, +.450 ],
	    [ "B", +.325, +.325 ],
	    [ "C", +.425, +.150 ],
	    [ "D", +.450, -.075 ],
	    [ "E", +.375, -.275 ],
	    [ "F", +.200, -.400 ],
	    [ "G",  .000, -.450 ],
	    [ "H", -.200, -.400 ],
	    [ "J", -.375, -.275 ],
	    [ "K", -.450, -.075 ],
	    [ "L", -.425, +.150 ],
	    [ "M", -.325, +.325 ],
	    [ "N", -.100, +.450 ],
	    [ "P",  .000, +.325 ],
	    [ "R", +.150, +.300 ],
	    [ "S", +.250, +.175 ],
	    [ "T", +.325, +.025 ],
	    [ "U", +.300, -.125 ],
	    [ "V", +.200, -.250 ],
	    [ "W",  .000, -.300 ],
	    [ "X", -.200, -.250 ],
	    [ "Y", -.300, -.125 ],
	    [ "Z", -.325, +.025 ],
	    [ "a", -.250, +.175 ],
	    [ "b", -.150, +.300 ],
	    [ "c", +.100, +.150 ],
	    [ "d", +.150,  .000 ],
	    [ "e", +.075, -.150 ],
	    [ "f", -.075, -.150 ],
	    [ "g", -.150,  .000 ],
	    [ "h", -.100, +.150 ],
	    [ "j",  .000,  .000 ],
	],
	"22-34" => [
	    [ 20, ],
	    [ 62, 142, 218, 298 ],
	    [ "A",  .000, +.450 ],
	    [ "B", +.175, +.425 ],
	    [ "C", +.325, +.325 ],
	    [ "D", +.425, +.175 ],
	    [ "E", +.450, +.025 ],
	    [ "F", +.450, -.125 ],
	    [ "G", +.375, -.275 ],
	    [ "H", +.250, -.375 ],
	    [ "J", +.100, -.450 ],
	    [ "K", -.100, -.450 ],
	    [ "L", -.250, -.375 ],
	    [ "M", -.375, -.275 ],
	    [ "N", -.450, -.125 ],
	    [ "P", -.450, +.025 ],
	    [ "R", -.425, +.175 ],
	    [ "S", -.325, +.325 ],
	    [ "T", -.175, +.425 ],
	    [ "U",  .000, +.300 ],
	    [ "V", +.200, +.225 ],
	    [ "W", +.300, +.050 ],
	    [ "X", +.300, -.100 ],
	    [ "Y", +.150, -.250 ],
	    [ "Z",  .000, -.300 ],
	    [ "a", -.150, -.250 ],
	    [ "b", -.300, -.100 ],
	    [ "c", -.300, +.050 ],
	    [ "d", -.200, +.225 ],
	    [ "e",  .000, +.150 ],
	    [ "f", +.150, +.050 ],
	    [ "g", +.150, -.100 ],
	    [ "h",  .000, -.150 ],
	    [ "j", -.150, -.100 ],
	    [ "k", -.150, +.050 ],
	    [ "l",  .000,  .000 ],
	],
	"22-41" => [
	    [ 20, ],
	    [ 39, 135, 264, undef ],
	    [ "A", +.132, +.472 ],
	    [ "B", +.255, +.418 ],
	    [ "C", +.358, +.334 ],
	    [ "D", +.435, +.225 ],
	    [ "E", +.480, +.099 ],
	    [ "F", +.489, -.034 ],
	    [ "G", +.462, -.165 ],
	    [ "H", +.400, -.283 ],
	    [ "J", +.308, -.381 ],
	    [ "K", +.194, -.450 ],
	    [ "L", +.067, -.486 ],
	    [ "M", -.067, -.486 ],
	    [ "N", -.194, -.450 ],
	    [ "P", -.308, -.381 ],
	    [ "R", -.400, -.283 ],
	    [ "S", -.462, -.165 ],
	    [ "T", -.489, -.034 ],
	    [ "U", -.480, +.099 ],
	    [ "V", -.435, +.225 ],
	    [ "W", -.358, +.334 ],
	    [ "X", -.255, +.418 ],
	    [ "Y", -.132, +.472 ],
	    [ "Z",  .000, +.376 ],
	    [ "a", +.163, +.282 ],
	    [ "b", +.299, +.173 ],
	    [ "c", +.326,  .000 ],
	    [ "d", +.308, -.173 ],
	    [ "e", +.163, -.282 ],
	    [ "f",  .000, -.344 ],
	    [ "g", -.163, -.282 ],
	    [ "h", -.308, -.173 ],
	    [ "i", -.326,  .000 ],
	    [ "j", -.299, +.173 ],
	    [ "k", -.163, +.282 ],
	    [ "m",  .000, +.188 ],
	    [ "n", +.163, +.094 ],
	    [ "p", +.163, -.094 ],
	    [ "q",  .000, -.188 ],
	    [ "r", -.163, -.094 ],
	    [ "s", -.163, +.094 ],
	    [ "t",  .000,  .000 ],
	],
	"22-55" => [
	    [ 20, ],
	    [ 30, 142, 226, 314 ],
	    [ "A", +.112, +.455 ],
	    [ "B", +.225, +.390 ],
	    [ "C", +.336, +.325 ],
	    [ "D", +.450, +.130 ],
	    [ "E", +.450,  .000 ],
	    [ "F", +.450, -.130 ],
	    [ "G", +.336, -.325 ],
	    [ "H", +.225, -.390 ],
	    [ "J", +.112, -.455 ],
	    [ "K", -.112, -.455 ],
	    [ "L", -.225, -.390 ],
	    [ "M", -.336, -.325 ],
	    [ "N", -.450, -.130 ],
	    [ "P", -.450,  .000 ],
	    [ "R", -.450, +.130 ],
	    [ "S", -.336, +.325 ],
	    [ "T", -.225, +.390 ],
	    [ "U", -.112, +.455 ],
	    [ "V",  .000, +.390 ],
	    [ "W", +.112, +.325 ],
	    [ "X", +.225, +.260 ],
	    [ "Y", +.336, +.195 ],
	    [ "Z", +.336, +.065 ],
	    [ "a", +.336, -.065 ],
	    [ "b", +.336, -.195 ],
	    [ "c", +.225, -.260 ],
	    [ "d", +.112, -.325 ],
	    [ "e",  .000, -.390 ],
	    [ "f", -.112, -.325 ],
	    [ "g", -.225, -.260 ],
	    [ "h", -.336, -.195 ],
	    [ "i", -.336, -.065 ],
	    [ "j", -.336, +.065 ],
	    [ "k", -.336, +.195 ],
	    [ "m", -.225, +.260 ],
	    [ "n", -.112, +.325 ],
	    [ "p",  .000, +.260 ],
	    [ "q", +.112, +.195 ],
	    [ "r", +.225, +.130 ],
	    [ "s", +.225,  .000 ],
	    [ "t", +.225, -.130 ],
	    [ "u", +.112, -.195 ],
	    [ "v",  .000, -.260 ],
	    [ "w", -.112, -.195 ],
	    [ "x", -.225, -.130 ],
	    [ "y", -.225,  .000 ],
	    [ "z", -.225, +.130 ],
	    [ "AA", -.112, +.195 ],
	    [ "BB",  .000, +.130 ],
	    [ "CC", +.112, +.065 ],
	    [ "DD", +.112, -.065 ],
	    [ "EE",  .000, -.130 ],
	    [ "FF", +.112, -.065 ],
	    [ "GG", +.112, +.065 ],
	    [ "HH",  .000,  .000 ],
	],
	"22-95" => [
	    [ 20, ],
	    [ 26, 180, 266, undef ],
	    [ "A",  .000, +.470 ],
	    [ "B", +.138, +.449 ],
	    [ "C", +.265, +.388 ],
	    [ "D", +.367, +.293 ],
	    [ "E", +.437, +.172 ],
	    [ "F", +.469, +.035 ],
	    [ "G", +.458, -.104 ],
	    [ "H", +.407, -.234 ],
	    [ "J", +.320, -.344 ],
	    [ "K", +.205, -.423 ],
	    [ "L", +.070, -.465 ],
	    [ "M", -.070, -.465 ],
	    [ "N", -.205, -.423 ],
	    [ "P", -.320, -.344 ],
	    [ "R", -.407, -.234 ],
	    [ "S", -.458, -.104 ],
	    [ "T", -.469, +.035 ],
	    [ "U", -.437, +.172 ],
	    [ "V", -.367, +.293 ],
	    [ "W", -.265, +.388 ],
	    [ "X", -.138, +.449 ],
	    [ "Y",  .000, +.250 ],
	    [ "Z", +.191, +.283 ],
	    [ "a", +.238, +.077 ],
	    [ "b", +.309, -.100 ],
	    [ "c", +.147, -.202 ],
	    [ "d",  .000, -.325 ],
	    [ "e", -.147, -.202 ],
	    [ "f", -.309, -.100 ],
	    [ "g", -.238, +.077 ],
	    [ "h", -.191, +.283 ],
	    [ "i",  .000,  .000 ],
	],
	"22-96" => [
	    [ 8, ],
	    [ 19, 41, undef, undef ],
	    [ "A",  .000, +.360 ],
	    [ "B", +.312, +.180 ],
	    [ "C", +.312, -.180 ],
	    [ "D",  .000, -.360 ],
	    [ "E", -.312, -.180 ],
	    [ "F", -.312, +.180 ],
	    [ "G",  .000,  .000 ],
	],
	"24-19" => [
	    [ 12, 2 ],
	    [ 30, 165, 315, undef ],
	    [ "A",  .000, +.412 ],
	    [ "B", +.238, +.412 ],
	    [ "C", +.357, +.206 ],
	    [ "D", +.476,  .000 ],
	    [ "E", +.357, -.206 ],
	    [ "F", +.238, -.412 ],
	    [ "G",  .000, -.412 ],
	    [ "H", -.238, -.412 ],
	    [ "J", -.357, -.206 ],
	    [ "K", -.476,  .000 ],
	    [ "L", -.357, +.206 ],
	    [ "M", -.238, +.412 ],
	    [ "N", -.119, +.206 ],
	    [ "P", +.119, +.206 ],
	    [ "R", +.238,  .000 ],
	    [ "S", +.119, -.206 ],
	    [ "T", -.119, -.206 ],
	    [ "U", -.238,  .000 ],
	    [ "V",  .000,  .000 ],
	],
	"24-27" => [
	    [ 12, ],
	    [ 45, 110, 140, 225 ],
	    [ "A",  .000, +.491 ],
	    [ "B", +.246, +.425 ],
	    [ "C", +.425, +.246 ],
	    [ "D", +.491,  .000 ],
	    [ "E", +.425, -.246 ],
	    [ "F", +.246, -.425 ],
	    [ "G",  .000, -.491 ],
	    [ "H", -.246, -.425 ],
	    [ "J", -.425, -.246 ],
	    [ "K", -.491,  .000 ],
	    [ "L", -.425, +.246 ],
	    [ "M", -.246, +.425 ],
	    [ "N",  .000, +.255 ],
	    [ "P", +.184, +.239 ],
	    [ "R", +.270, +.130 ],
	    [ "S", +.301,  .000 ],
	    [ "T", +.210, -.156 ],
	    [ "U",  .000, -.255 ],
	    [ "V", -.210, -.156 ],
	    [ "W", -.301,  .000 ],
	    [ "X", -.270, +.130 ],
	    [ "Y", -.184, +.239 ],
	    [ "Z", +.137, +.103 ],
	    [ "a", +.088, -.022 ],
	    [ "b", -.088, -.022 ],
	    [ "c", -.137, +.103 ],
	    [ "d",  .000, +.075 ],
	],
	"24-31" => [
	    [ 16, ],
	    [ 90, 225, 255, undef ],
	    [ "A", +.158, +.455 ],
	    [ "B", +.316, +.364 ],
	    [ "C", +.474, +.091 ],
	    [ "D", +.474, -.091 ],
	    [ "E", +.316, -.364 ],
	    [ "F", +.158, -.455 ],
	    [ "G", -.158, -.455 ],
	    [ "H", -.316, -.364 ],
	    [ "J", -.474, -.091 ],
	    [ "K", -.474, +.091 ],
	    [ "L", -.316, +.364 ],
	    [ "M", -.158, -.455 ],
	    [ "N",  .000, +.364 ],
	    [ "P", +.158, +.273 ],
	    [ "Q", +.316, +.182 ],
	    [ "R", +.316,  .000 ],
	    [ "S", +.316, -.182 ],
	    [ "T", +.158, -.273 ],
	    [ "U",  .000, -.364 ],
	    [ "V", -.158, -.273 ],
	    [ "W", -.316, -.182 ],
	    [ "X", -.316,  .000 ],
	    [ "Y", -.316, +.182 ],
	    [ "Z", -.158, +.273 ],
	    [ "a",  .000, +.182 ],
	    [ "b", +.158, +.091 ],
	    [ "c", +.158, -.091 ],
	    [ "d",  .000, -.182 ],
	    [ "e", -.158, -.091 ],
	    [ "f", -.158, +.091 ],
	    [ "g",  .000,  .000 ],
	],
	"24-61" => [
	    [ 20, ],
	    [ 90, 180, 270, 324 ],
	    [ "A", +.196, +.500 ],
	    [ "B", +.314, +.435 ],
	    [ "C", +.413, +.343 ],
	    [ "D", +.485, +.230 ],
	    [ "E", +.527, +.101 ],
	    [ "F", +.536, -.030 ],
	    [ "G", +.511, -.164 ],
	    [ "H", +.454, -.287 ],
	    [ "J", +.368, -.391 ],
	    [ "K", +.259, -.470 ],
	    [ "L", +.134, -.519 ],
	    [ "M",  .000, -.537 ],
	    [ "N", -.134, -.519 ],
	    [ "P", -.259, -.470 ],
	    [ "R", -.368, -.391 ],
	    [ "S", -.454, -.287 ],
	    [ "T", -.511, -.164 ],
	    [ "U", -.536, -.030 ],
	    [ "V", -.527, +.101 ],
	    [ "W", -.485, +.230 ],
	    [ "X", -.413, +.343 ],
	    [ "Y", -.314, +.435 ],
	    [ "Z", -.196, +.500 ],
	    [ "a", -.068, +.454 ],
	    [ "b", +.068, +.454 ],
	    [ "c", +.173, +.363 ],
	    [ "d", +.285, +.283 ],
	    [ "e", +.362, +.175 ],
	    [ "f", +.399, +.046 ],
	    [ "g", +.392, -.088 ],
	    [ "h", +.341, -.213 ],
	    [ "i", +.251, -.314 ],
	    [ "j", +.133, -.379 ],
	    [ "k",  .000, -.402 ],
	    [ "m", -.133, -.379 ],
	    [ "n", -.251, -.314 ],
	    [ "p", -.341, -.213 ],
	    [ "q", -.392, -.088 ],
	    [ "r", -.399, +.046 ],
	    [ "s", -.362, +.175 ],
	    [ "t", -.285, +.283 ],
	    [ "u", -.173, +.363 ],
	    [ "v",  .000, +.338 ],
	    [ "w", +.147, +.223 ],
	    [ "x", +.237, +.122 ],
	    [ "y", +.267, -.010 ],
	    [ "z", +.228, -.139 ],
	    [ "AA", +.131, -.233 ],
	    [ "BB",  .000, -.267 ],
	    [ "CC", -.131, -.233 ],
	    [ "DD", -.228, -.139 ],
	    [ "EE", -.267, -.010 ],
	    [ "FF", -.237, +.122 ],
	    [ "GG", -.147, +.223 ],
	    [ "HH",  .000, +.200 ],
	    [ "JJ", +.105, +.094 ],
	    [ "KK", +.135, -.041 ],
	    [ "LL",  .000, -.132 ],
	    [ "MM", -.135, -.041 ],
	    [ "NN", -.105, +.094 ],
	    [ "PP",  .000,  .000 ],
	],
    );
#    my %ltr;
#    for my $k (keys %mil_std_1669_pin_arrangement) {
#	my @arr = @{$mil_std_1669_pin_arrangement{$k}};
#	shift @arr;
#	shift @arr;
#	my $str = "";
#	for my $r (@arr) {
#	    $str .= " " . $$r[0];
#	}
#	if (!defined($ltr{$str})) {
#	    $ltr{$str} = $k;
#	} else {
#	    $ltr{$str} .= " " . $k;
#	}
#    }
#    for my $k (sort keys %ltr) {
#	my $v = $ltr{$k};
#	print "$k: $v\n";
#    }
#    return
    $doc .= "# http://everyspec.com/ MIL-DTL-26482H_AMENDMENT-2.pdf\n";
    # From what I understand, panel mounted connectors are always of the "receptacle" type
    # page 86, 88 .. 90, dimensions
    # A package location
    # B (see note 1)
    # C socket insert location
    # D pin contact location
    # E (see note 4)
    # F pin insert location
    # G bay pin dia
    # H bay pin location
    # J pin contact location
    # K pin insert location
    # L (see note 1)
    # M socket insert location
    # N shoulder location
    # P max insert dia
    # R shell ID
    # S dia over keyways
    # T shell OD
    # U dia over bays
    # V cpig R groove dia
    # W cpig R ID
    # X dia over keys
    # Y shell OD
    # Z min shell ID
    # AA (see note 5)
    # CC socket insert
    # FF pin insert
    # GG bay pin groove
    # KK pin insert
    my @mil_dtl_26482_hdr =
	qw/       A      B      C      D      E     F     G        H      J      K      L      M      N      P      R      S      T      U      V      W      X      Y      Z     AA     CC     FF     GG     KK /;
    my %mil_dtl_26482_dim = (
	8  => [ 0.382, 0.114, 0.015, 0.070, 0.113, 0.040, 0.080, 0.100, 0.080, 0.322, 0.104, 0.347, 0.353, 0.285, 0.364, 0.412, 0.471, 0.555, 0.576, 0.483, 0.398, 0.355, 0.292, 0.325, 0.014, 0.035, 0.098, 0.326 ],
	10 => [ 0.382, 0.114, 0.015, 0.070, 0.113, 0.040, 0.080, 0.100, 0.080, 0.322, 0.104, 0.347, 0.353, 0.402, 0.492, 0.540, 0.588, 0.672, 0.697, 0.604, 0.526, 0.483, 0.409, 0.325, 0.014, 0.035, 0.098, 0.326 ],
	12 => [ 0.382, 0.114, 0.015, 0.070, 0.113, 0.040, 0.080, 0.100, 0.080, 0.322, 0.104, 0.347, 0.353, 0.516, 0.609, 0.689, 0.748, 0.851, 0.871, 0.763, 0.675, 0.595, 0.523, 0.325, 0.014, 0.035, 0.098, 0.326 ],
	14 => [ 0.382, 0.114, 0.015, 0.070, 0.113, 0.040, 0.080, 0.100, 0.080, 0.322, 0.104, 0.347, 0.353, 0.641, 0.734, 0.814, 0.873, 0.976, 0.995, 0.887, 0.800, 0.720, 0.648, 0.325, 0.014, 0.035, 0.098, 0.326 ],
	16 => [ 0.382, 0.114, 0.015, 0.070, 0.113, 0.040, 0.080, 0.100, 0.080, 0.322, 0.104, 0.347, 0.353, 0.766, 0.860, 0.939, 0.998, 1.100, 1.120, 1.012, 0.925, 0.845, 0.772, 0.325, 0.014, 0.035, 0.098, 0.326 ],
	18 => [ 0.382, 0.114, 0.015, 0.070, 0.113, 0.040, 0.080, 0.100, 0.080, 0.322, 0.104, 0.347, 0.353, 0.855, 0.964, 1.039, 1.123, 1.225, 1.245, 1.138, 1.025, 0.945, 0.862, 0.325, 0.014, 0.035, 0.098, 0.326 ],
	20 => [ 0.444, 0.176, 0.077, 0.070, 0.113, 0.102, 0.080, 0.100, 0.152, 0.384, 0.104, 0.409, 0.415, 0.980, 1.089, 1.164, 1.248, 1.350, 1.370, 1.262, 1.150, 1.070, 0.987, 0.387, 0.076, 0.097, 0.098, 0.388 ],
	22 => [ 0.444, 0.176, 0.077, 0.070, 0.113, 0.102, 0.080, 0.100, 0.152, 0.384, 0.104, 0.409, 0.415, 1.105, 1.214, 1.289, 1.373, 1.475, 1.495, 1.387, 1.275, 1.195, 1.111, 0.387, 0.076, 0.097, 0.098, 0.388 ],
	24 => [ 0.444, 0.176, 0.077, 0.070, 0.152, 0.102, 0.127, 0.109, 0.152, 0.384, 0.104, 0.409, 0.415, 1.229, 1.339, 1.414, 1.498, 1.602, 1.624, 1.512, 1.400, 1.320, 1.237, 0.387, 0.076, 0.097, 0.145, 0.388 ],
    );
    #my %mil_dtl_26482_ix;
    #for (my $ix = 0; $ix < @mil_dtl_26482_hdr; $ix++) { $mil_dtl_26482_ix{$mil_dtl_26482_hdr[$ix]} = $ix; }

    # p.87, master and minor key widths
    my @key_width = (
	# master, minor key
	[ .129, .066 ], # receptacle
	[ .112, .044 ], # plug
    );
    # p.91 angles from master key (top)
    my @key_angle = map { $_ - 90 } ( 105, 140, 215, 265 ); # rotated same way as pcb for receptacle
    my @bayonet_angle = map { angleCompass2pcb($_) } ( 60, 180, 300 );

    # make body silk for receptacle facing
    my %mil_dtl_26482_body = ();
    silk_width(0.12);
    for my $shell (keys %mil_dtl_26482_dim) {
	my ($A, $B, $C, $D, $E, $F, $G, $H, $J, $K, $L, $M, $N, $P, $R, $S, $T, $U, $V, $W, $X, $Y, $Z,
	    $AA, $CC, $FF, $GG, $KK, ) = map { inch_to_mm($_) } @{$mil_dtl_26482_dim{$shell}};
	$pr_save = "";
	pr_inc();
	{
	    pr("# bayonet pins\n");
	    my $h1 = circle_segment_h($T/2,$G);
	    my $h2 = circle_segment_h($U/2,$G); # guess that byonet pin corners are inside dia $U
	    my @bp = ( # 0 degree is left in pcb
		[ -$T/2 + $h1, -$G/2 ],
		[ -$U/2 + $h2, -$G/2 ],
		[ -$U/2 + $h2,  $G/2 ],
		[ -$T/2 + $h1,  $G/2 ],
	    );
	    for my $a (@bayonet_angle) {
		rot_init($a);
		my @p = map { vrot($_) } @bp;
		silk_vstart(shift @p);
		for my $p (@p) { silk_vline($p); }
	    }
	}
	pr("# shell outer dia\n");
	silk_circle($origin, $T/2);
	{
	    pr("# keyways (receptacle) master key\n");
	    my $kw = inch_to_mm($key_width[0][0]);
	    my $h1 = circle_segment_h($R/2,$kw);
	    my @bp = (
		[ - $R/2 + $h1, -$kw/2 ],
		[ - $S/2      , -$kw/2 ],
		[ - $S/2      ,  $kw/2 ],
		[ - $R/2 + $h1,  $kw/2 ],
	    );
	    my $a = angleCompass2pcb(0);
	    rot_init($a);
	    my @p = map { vrot($_) } @bp;
	    silk_vstart(shift @p);
	    for my $p (@p) { silk_vline($p); }
	}
	{
	    pr("# keyways (receptacle) minor keys\n");
	    my $kw = inch_to_mm($key_width[0][1]);
	    my $h1 = circle_segment_h($R/2,$kw);
	    my @bp = (
		[ - $R/2 + $h1, -$kw/2 ],
		[ - $S/2      , -$kw/2 ],
		[ - $S/2      ,  $kw/2 ],
		[ - $R/2 + $h1,  $kw/2 ],
	    );
	    for my $a (@key_angle) {
		rot_init($a);
		my @p = map { vrot($_) } @bp;
		silk_vstart(shift @p);
		for my $p (@p) { silk_vline($p); }
	    }
	}
	{
	    pr("# shell inner dia with cutouts for keys\n");
	    my $kw = inch_to_mm($key_width[0][0]); # master key
	    my $da = Asin($kw/$R);
	    my $sta_angle = -90+$da;
	    my $end_angle = 270-$da;
	    my $curr_angle = $sta_angle;

	    $kw = inch_to_mm($key_width[0][1]); # minor keys
	    $da = Asin($kw/$R);
	    for my $a (@key_angle) {
		my $nxt = $a - $da;
		silk_arc($origin, $R/2, $curr_angle, $nxt - $curr_angle);
		$curr_angle = $a + $da;
	    }
	    silk_arc($origin, $R/2, $curr_angle, $end_angle - $curr_angle);
	}

	pr_dec();
	$mil_dtl_26482_body{$shell} = $pr_save;
    }
    $pr_save = "";
    silk_width();

    ####################
    $doc .= "# http://amphenol.co.kr/board/product/011-ads-PCB-Cylindrical-Connector.pdf\n";
    my %mil_alt_rotation_letter = ( # p.26
	P  => "P", S  => "S", # no rotation
	PW => "G", PX => "I", PY => "K", PZ => "M",
	SW => "H", SX => "J", SY => "L", SZ => "N",
    );
    my $pt0xpin = 0.030;
    my %pt02 = (     # PT02 p.41
	# part number to be followed with insert arrangement and rotation
	# size part number        A      K       L      M       N       R       S      Z
	 6  => [ "58-570120-",   .348,  .493,   .825,  .431,   .323,   .469,   .688,  .380 ],
	 8  => [ "58-570121-",   .473,  .493,   .825,  .431,   .449,   .594,   .812,  .380 ],
	 10 => [ "58-570122-",   .590,  .493,   .825,  .431,   .573,   .719,   .938,  .380 ],
	 12 => [ "58-570123-",   .750,  .493,   .825,  .431,   .699,   .812,  1.031,  .380 ],
	 14 => [ "58-570124-",   .875,  .493,   .825,  .431,   .823,   .906,  1.125,  .380 ],
	 16 => [ "58-570125-",  1.000,  .493,   .825,  .431,   .949,   .969,  1.219,  .380 ],
	 18 => [ "58-570126-",  1.125,  .493,   .825,  .431,  1.073,  1.062,  1.312,  .380 ],
	 20 => [ "58-570127-",  1.250,  .650,  1.076,  .556,  1.199,  1.156,  1.438,  .286 ],
	 22 => [ "58-570128-",  1.375,  .650,  1.076,  .556,  1.323,  1.250,  1.562,  .286 ],
	 24 => [ "58-570129-",  1.500,  .683,  1.109,  .589,  1.449,  1.375,  1.688,  .253 ],
    );
    my %pt07 = ( # PT07 p.42
	# size part number      A      H      J      K      M     Pmin  Pmax        R             S      Z
	6  => [ "58-533720-",  .348,  .625,  .405,  .125,  .696,  .062, .125,  ".4375-28 UNEF",  .812,  .376 ],
	8  => [ "58-533721-",  .473,  .750,  .530,  .125,  .696,  .062, .125,  ".5625-24 UNEF",  .938,  .376 ],
	10 => [ "58-533722-",  .590,  .875,  .655,  .125,  .696,  .062, .125,  ".6875-24 UNEF", 1.062,  .376 ],
	12 => [ "58-533723-",  .750, 1.062,  .818,  .125,  .696,  .062, .125,  ".8750-20 UNEF", 1.250,  .376 ],
	14 => [ "58-533724-",  .875, 1.188,  .942,  .125,  .696,  .062, .125, "1.0000-20 UNEF", 1.375,  .376 ],
	16 => [ "58-533725-", 1.000, 1.312, 1.066,  .125,  .696,  .062, .125, "1.1250-18 UNEF", 1.500,  .376 ],
	18 => [ "58-533726-", 1.125, 1.438, 1.191,  .125,  .696,  .062, .125, "1.2500-18 UNEF", 1.625,  .376 ],
	20 => [ "58-533727-", 1.250, 1.562, 1.316,  .156,  .884,  .062, .250, "1.3750-18 UNEF", 1.812,  .367 ],
	22 => [ "58-533728-", 1.375, 1.688, 1.441,  .156,  .884,  .062, .250, "1.5000-18 UNEF", 1.938,  .367 ],
	24 => [ "58-533729-", 1.500, 1.816, 1.566,  .156,  .917,  .062, .250, "1.6250-18 UNEF", 2.062,  .334 ],
    );
    # p.4 column MIL-C-26482
    my @insert = qw/ 8-3 8-98 10-5 10-6 12-3 12-10 14-18 14-19 16-26 18-11 18-32 20-27 20-41 22-55 24-31 24-61 /;
    # 22-36 on p.26 must be misprint, it probably is 20-27
    my %extra = ( # not in mil_std_1669, p.7, 26
	"10-5" => [
	    [ 20, ],
	    [ 45, 151, 180, 270 ],
	    [ "A", +.065, +.056 ],
	    [ "B", +.113, -.065 ],
	    [ "C",  .000, -.130 ],
	    [ "D", -.113, -.065 ],
	    [ "E", -.065, +.056 ],
	],
    );
    # bodies for PT02 and PT07
    my %pt02_body;
    for my $shell (keys %pt02) {
	my @arr = @{$pt02{$shell}};
	shift @arr; # skip part number
	my ($A, $K, $L, $M, $N, $R, $S, $Z) = map { inch_to_mm($_) } @arr;
	$pr_save = "";
	pr_inc();
	silk_width(0.12);
	my $hole_radi = inch_to_mm(0.120)/2;
	pr("# mounting holes\n");
	silk_circle([-$R/2,-$R/2], $hole_radi);
	silk_circle([-$R/2, $R/2], $hole_radi);
	silk_circle([ $R/2, $R/2], $hole_radi);
	silk_circle([ $R/2,-$R/2], $hole_radi);
	pr("# outline\n");
	silk_width();
	my $radius = ($S - $R)/2;
	silk_arc([-$R/2,-$R/2], $radius, -90, 90);
	silk_arc([-$R/2, $R/2], $radius,   0, 90);
	silk_arc([ $R/2, $R/2], $radius,  90, 90);
	silk_arc([ $R/2,-$R/2], $radius, 180, 90);
	silk_start(-$S/2, -$R/2); silk_rline(0,$R);
	silk_start(-$R/2,  $S/2); silk_rline($R,0);
	silk_start( $S/2,  $R/2); silk_rline(0,-$R);
	silk_start( $R/2, -$S/2); silk_rline(-$R,0);
	pr_dec();
	$pt02_body{$shell} = $pr_save;
    }
    my %pt07_body;
    for my $shell (keys %pt07) {
	my @arr = @{$pt07{$shell}};
	shift @arr; # skip part number
	$arr[7] =~ s/-.*//; # use just the tread diameter
	my ($A, $H, $J, $K, $M, $Pmin, $Pmax, $R, $S, $Z) = map { inch_to_mm($_) } @arr;
	$pr_save = "";
	pr_inc();
	{
	    pr("# tread with flat\n");
	    silk_width(0.12);
	    silk_circle_flat($origin, $R/2, $J - $R/2, 270);
	}
	{
	    pr("# flange\n");
	    silk_width();
	    my $flange_dia = $S * 1.1; # my guess
	    my $da = Acos($S/$flange_dia);
	    my $sweep = 90 - 2*$da;
	    my $side = triangle_x($flange_dia, $S);
	    silk_start($side/2, -$S/2);
	    silk_rline(-$side,0);
	    silk_start(-$S/2, -$side/2);
	    silk_rline(0, $side);
	    silk_start(-$side/2, $S/2);
	    silk_rline($side,0);
	    silk_start($S/2, $side/2);
	    silk_rline(0, -$side);

	    for my $a (( -90, 0, 90, 180)) {
		silk_arc($origin, $flange_dia/2, $a+$da, $sweep);
	    }
	}
	pr_dec();
	$pt07_body{$shell} = $pr_save;
    }
    $pr_save = "";

    my $drill = lead_to_drill(inch_to_mm($pt0xpin));
    my @thickness = drill2thickness($drill);

    $round_first_pin = 1;
    for my $insert (@insert) {
	my ($shell, $arrangement) = split(/-/, $insert);

	my $r = $mil_std_1669_pin_arrangement{$insert};
	if (!defined($r)) { $r = $extra{$insert}; }
	if (!defined($r)) { print "no such insert <$insert>\n"; next; }
	my ($mil1669def, $mil1669rotation, @mil1669pa) = @$r;
	# need min dist between pins
	my $spacing = 1000; # some max value
	for (my $ix = 0; $ix < @mil1669pa; $ix++) {
	    for (my $jx = $ix+1; $jx < @mil1669pa; $jx++) {
		my $dx = $mil1669pa[$ix][1] - $mil1669pa[$jx][1];
		my $dy = $mil1669pa[$ix][2] - $mil1669pa[$jx][2];
		my $dist = triangle_r($dx, $dy);
		if ($dist < $spacing) { $spacing = $dist; }
	    }
	}
	#print "$insert: $spacing\n";
	$spacing = inch_to_mm($spacing);

	my @dim26482 = @{$mil_dtl_26482_dim{$shell}};

	my ($part, $A, $H, $J, $K, $M, $Pmin, $Pmax, $R, $S, $Z) = @{$pt07{$shell}};

	#print "<$insert, $shell, $arrangement>\n";
	for my $type (qw/P S/) {
	    my @rot = (0, @$mil1669rotation);
	    for (my $rx = 0; $rx < @rot; $rx++) {
		my $angle = $rot[$rx];
		next if (!defined($angle));
		rot_init(-$angle); # rotate clockwise
		my $rot_letter = "_";
		if ($rx > 0) { $rot_letter = $mil_std_1669_rotation[$rx-1]; }

		for (my $tx = 0; $tx < @thickness; $tx++) {
		    my $file;
		    my $limit_radius = $thickness[$tx]/2 + $mask_gap;
		    if ($spacing/2 < $limit_radius) {
			#warn "$file: too close spacing <$spacing $limit_radius";
			next;
		    }
		    # using "insert" name based file name

		    {   # PT02
			$file = sprintf("Amphenol_pt02_%02d-%02d%s%s%s.fp", $shell, $arrangement, $type, $rot_letter,
					thickness_suffix($tx));

			element_start($file, $doc);
			pr("# pin configuration $insert\n");
			for my $r (@mil1669pa) {
			    my ($pname, $x, $y, @rest) = @$r;
			    $x = inch_to_mm( $x);
			    $y = inch_to_mm(-$y);
			    ($x, $y) = rot($x, $y);
			    if ($type eq "S") { $x = -$x; }
			    pin( $x, $y, $drill, $thickness[$tx], $pname, "", $pname);
			}
			pr($mil_dtl_26482_body{$shell},1);
			pr($pt02_body{$shell},1);
			element_stop();
		    }
		    {   # PT07
			$file = sprintf("Amphenol_pt07_%02d-%02d%s%s%s.fp", $shell, $arrangement, $type, $rot_letter,
					thickness_suffix($tx));

			element_start($file, $doc);
			pr("# pin configuration $insert\n");
			for my $r (@mil1669pa) {
			    my ($pname, $x, $y, @rest) = @$r;
			    $x = inch_to_mm( $x);
			    $y = inch_to_mm(-$y);
			    ($x, $y) = rot($x, $y);
			    if ($type eq "S") { $x = -$x; }
			    pin( $x, $y, $drill, $thickness[$tx], $pname, "", $pname);
			}
			pr($mil_dtl_26482_body{$shell},1);
			pr($pt07_body{$shell},1);
			element_stop();
		    }
		}
	    }
	}
    }
    $round_first_pin = 0;
}
#gen_mil();

########################################
### dsub stuff:
# wider pin row is down
# pin 1, socket lower left, pins lower right
# footprint origo is mid mounting holes

# http://www.dscc.dla.mil/Downloads/MilSpec/Docs/MIL-DTL-24308/dtl24308.pdf

# p. 9: (no sz 0, its a dummy)
my @dsub_mating = ( 0, 0.265 * 25.4, 0.265 * 25.4,  0.256 * 25.4,  0.256 * 25.4,  0.256 * 25.4,  0.256 * 25.4 );

# p.25 TABLE XIV
# we are only interested in pcb connectors here, i.e. M24308/23 M24308/24, see below

# p. 27:
my %dsub_sz20 = (  9 => 1, 15 => 2, 25 => 3, 37 => 4, 50 => 5, );
my %dsub_sz22 = ( 15 => 1, 26 => 2, 44 => 3, 62 => 4, 78 => 5, 104 => 6 ); # note: 104 not available for pcb
my %dsub_sz   = (  9 => 1, "15_1" => 1, "15_2" => 2, 25 => 3, 26 => 2, 37 => 4, 44 => 3, 50 => 5, 62 => 4, 78 => 5, 104 => 6 );

# p. 28..38: Appendix A, pin positions
# numbering for pins, socket numbering is reverse
# note: I use wider row lowest so I turned thoose pictures 180° around, i.e. pin 1 bocomes to the right
my %dsub_pos = (
    # values are in inches
    # size => arr of [ y displacement, x positions... ], starting with pin 1
    9 => [ # p.29
	[  0.056,  0.216, 0.108,  0.000, -0.108, -0.216 ],
	[ -0.056,  0.162, 0.054, -0.054, -0.162 ],
    ],
    "15_1" => [ # p.29
	[  0.078,  0.170, 0.080, -0.010, -0.100, -0.190 ],
	[  0.000,  0.215, 0.125,  0.035, -0.055, -0.145 ],
	[ -0.078,  0.170, 0.080, -0.010, -0.100, -0.190 ],
    ],
    "15_2" => [ # p.30
	[  0.056,  0.378, 0.270, 0.162, 0.054, -0.054, -0.162, -0.270, -0.378 ],
	[ -0.056,  0.324, 0.216, 0.108, 0.000, -0.108, -0.216, -0.324 ],
    ],
    26 => [ # p.30
	[  0.078,  0.340, 0.250, 0.160, 0.070, -0.020, -0.110, -0.200, -0.290, -0.380 ],
	[  0.000,  0.385, 0.295, 0.205, 0.115,  0.025, -0.065, -0.155, -0.245, -0.335 ],
	[ -0.078,  0.340, 0.250, 0.160, 0.070, -0.020, -0.110, -0.200, -0.290 ],
    ],
    25 => [ # p.31
	[  0.056,  0.652,  0.544,  0.435,  0.326,  0.218,  0.109,  0.000, -0.109, -0.218, -0.326, -0.435, -0.544, -0.652 ],
	[ -0.056,  0.598,  0.489,  0.381,  0.272,  0.163,  0.055, -0.055, -0.163, -0.272, -0.381, -0.489, -0.598 ],
    ],
    44 => [ # p.31
	[  0.078,  0.610, 0.520, 0.430, 0.340, 0.250, 0.160, 0.070, -0.020, -0.110, -0.200, -0.290, -0.380, -0.470, -0.560, -0.650 ],
	[  0.000,  0.655, 0.565, 0.475, 0.385, 0.295, 0.205, 0.115, 0.025, -0.065, -0.155, -0.245, -0.335, -0.425, -0.515, -0.605 ],
	[ -0.078,  0.610, 0.520, 0.430, 0.340, 0.250, 0.160, 0.070, -0.020, -0.110, -0.200, -0.290, -0.380, -0.470, -0.560, ],
    ],
    37 => [ # p.32
	[  0.056,  0.978,  0.870,  0.761,  0.652,  0.544,  0.435,  0.326,  0.218,  0.109,  0.000, -0.109, -0.218, -0.326, -0.435, -0.544, -0.652, -0.761, -0.870, -0.978 ],
	[ -0.056,  0.924,  0.815,  0.707,  0.598,  0.489,  0.381,  0.272,  0.163,  0.055, -0.055, -0.163, -0.272, -0.381, -0.489, -0.598, -0.707, -0.815, -0.924 ],
    ],
    62 => [ # p.33, pin 34: .1165 is probably a typo in the diagram, repl. with 0.1655
	[  0.078,  0.927 , 0.832 , 0.737 , 0.642 , 0.547 , 0.452 , 0.357 , 0.262 , 0.167 , 0.072 , -0.023 , -0.118 , -0.213 , -0.308 , -0.403 , -0.498 , -0.593 , -0.688 , -0.783 , -0.878 , -0.973  ],
	[  0.000,  0.9745, 0.8795, 0.7845, 0.6895, 0.5945, 0.4995, 0.4045, 0.3095, 0.2145, 0.1195,  0.0245, -0.0705, -0.1655, -0.2605, -0.3555, -0.4505, -0.5455, -0.6405, -0.7355, -0.8305, -0.9255 ],
	[ -0.078,  0.927 , 0.832 , 0.737 , 0.642 , 0.547 , 0.452 , 0.357 , 0.262 , 0.167 , 0.072 , -0.023 , -0.118 , -0.213 , -0.308 , -0.403 , -0.498 , -0.593 , -0.688 , -0.783 , -0.878 ],
    ],
    50 => [ # p.34, a few values had to be manually adjusted
	[  0.112,  0.870, 0.761, 0.652, 0.544, 0.435, 0.326, 0.218, 0.109,  0.000, -0.109, -0.218, -0.326, -0.435, -0.544, -0.652, -0.761, -0.870 ],
	[  0.000,  0.815, 0.707, 0.598, 0.489, 0.381, 0.272, 0.163, 0.055, -0.055, -0.163, -0.272, -0.381, -0.489, -0.598, -0.707, -0.815 ],
	[ -0.112,  0.870, 0.761, 0.652, 0.544, 0.435, 0.326, 0.218, 0.109,  0.000, -0.109, -0.218, -0.326, -0.435, -0.544, -0.652, -0.761, -0.870 ],
    ],
    78 => [ # p.35
	[  0.123,  0.9025, 0.8075, 0.7125, 0.6175, 0.5225, 0.4275, 0.3325, 0.2375, 0.1425, 0.0475, -0.0475, -0.1425, -0.2375, -0.3325, -0.4275, -0.5225, -0.6175, -0.7125, -0.8075, -0.9025 ],
	[  0.041,  0.855 , 0.760 , 0.665 , 0.570 , 0.475 , 0.380 , 0.285 , 0.190 , 0.095 , 0.000 , -0.095 , -0.190 , -0.285 , -0.380 , -0.475 , -0.570 , -0.665 , -0.760 , -0.855 ],
	[ -0.041,  0.9025, 0.8075, 0.7125, 0.6175, 0.5225, 0.4275, 0.3325, 0.2375, 0.1425, 0.0475, -0.0475, -0.1425, -0.2375, -0.3325, -0.4275, -0.5225, -0.6175, -0.7125, -0.8075, -0.9025 ],
	[ -0.123,  0.855 , 0.760 , 0.665 , 0.570 , 0.475 , 0.380 , 0.285 , 0.190 , 0.095 , 0.000 , -0.095 , -0.190 , -0.285 , -0.380 , -0.475 , -0.570 , -0.665 , -0.760 , -0.855 ],
    ],
    # p.36, 104 is not for pcb's
);
sub dsub_pos(;$) {
    my $f = shift;
    for my $k (sort keys %dsub_pos) {
	my $rx;
	my $r = $dsub_pos{$k};
	print "connector $k\n" if ($f);
	for ($rx = 0; $rx < @$r; $rx++) {
	    my $px;
	    print " row $rx\n" if ($f);
	    my $rr = $$r[$rx];
	    for ($px = 0; $px < @$rr; $px++) {
		$$rr[$px] *= 25.4;
		printf " %.2f", $$rr[$px] if ($f);
	    }
	    print "\n" if ($f);
	}
    }
}

sub dsub_gen62() {
    my $ix = 0.927;
    while ($ix > -1) {
	printf "%.3f, ", $ix;
	$ix -= 0.095;
    }
    print "\n";

    $ix = 0.9745;
    while ($ix > -1) {
	printf "%.4f, ", $ix;
	$ix -= 0.095;
    }
    print "\n";
}
sub dsub_gen50() {
    # a few values had to be manually adjusted to match diagram
    my $step = 0.10873;
    my $ix = 0.870;
    while ($ix > -0.9) {
	printf "%.3f, ", $ix;
	$ix -= $step;
    }
    print "\n";

    $ix = 0.8154;
    while ($ix > -0.9) {
	printf "%.3f, ", $ix;
	$ix -= $step;
    }
    print "\n";
}
sub dsub_gen78() {
    # a few values had to be manually adjusted to match diagram
    my $step = 0.095;
    my $ix = 0.9025;
    while ($ix > -0.91) {
	printf "%.4f, ", $ix;
	$ix -= $step;
    }
    print "\n";

    $ix = 0.855;
    while ($ix > -0.9) {
	printf "%.3f , ", $ix;
	$ix -= $step;
    }
    print "\n";
}
#dsub_gen62();
#dsub_gen50();
#dsub_gen78();

# shell receptable http://www.dscc.dla.mil/Downloads/MilSpec/Docs/MIL-DTL-24308/dtl24308ss23.pdf
# shell plug       http://www.dscc.dla.mil/Downloads/MilSpec/Docs/MIL-DTL-24308/dtl24308ss24.pdf

# p.1
my $dsub_Dangle = deg_rad(10); # 10 degrees typically
my $dsub_sin10 = sin($dsub_Dangle);
my $dsub_cos10 = cos($dsub_Dangle);
my $dsub_Dpradius = 0.104 * 25.4; # plug       "D" inner radius
my $dsub_Drradius = 0.100 * 25.4; # receptable "D" outer radius
my $dsub_Dbradius = 0.077 * 25.4; # pcb (back) side "D" radius

my $dsub_spacer20 = 0.251 * 25.4; # max
my $dsub_spacer22 = 0.375 * 25.4; # max

# p.4
my %dsub_dim = (
    # refer to page 1 for where measurements A-L are
    # data from tables on p.4 of the above, mean values (to 2 decimals, calc. from inch values), in mm
    # calc with aid of dsub_mean.pl
    # shell size 1 to 5, pos 0 is a dummy
    A  => [ 0,  30.81, 39.14, 53.04, 69.32, 66.93, ], # flage width
    Br => [ 0,  16.33, 24.66, 38.38, 54.84, 52.43, ], # "D" outer max width
    Bp => [ 0,  16.92, 25.25, 38.96, 55.42, 52.81, ], # "D" inner max width
    C  => [ 0,  24.99, 33.32, 47.04, 63.50, 61.11, ], # mounting hole distance
    Dr => [ 0,   7.90,  7.90,  7.90,  7.90, 10.74, ], # "D" outer max height
    Dp => [ 0,   8.36,  8.36,  8.36,  8.36, 11.20, ], # "D" inner max height
    E  => [ 0,  12.55, 12.55, 12.55, 12.55, 15.37, ], # flange height
    Fr => [ 0,  10.90, 10.90, 10.90, 10.90, 10.90, ], # metal part total heigt
    Fp => [ 0,  12.55, 12.55, 12.55, 12.55, 15.37, ], # metal part total heigt
    G  => [ 0,   6.17,  6.17,  6.17,  6.17,  6.17, ], # shroud height (mating side)
    H  => [ 0,  19.28, 27.51, 41.27, 57.71, 55.32, ], # "D" max width  on pcb side / (typo for sz extra ")" in "31.615)")
    J  => [ 0,  10.72, 10.72, 10.72, 10.72, 13.56, ], # "D" max height on pcb side
    K  => [ 0,   1.21,  1.21,  1.21,  1.21,  1.21, ], # flange rivet thickness
    L  => [ 0,   0.76,  0.76,  0.99,  0.99,  0.99, ], # flange thickness
);

sub dsub_mkpins($$ ; $$$$$) {
    my $pins = shift;
    my $ph   = shift; # pin hole size

    my $od       = shift; # pin hole cu annulus diameter
    my $socket   = shift; # not 0 => pin 1 lower left, else => pin 1 lower right
    my $pin_name = shift; # ref to arr with pin names

    my $rd       = shift; # row distance/separation, usually 2.84, angled european = 2.54
    my $pitch    = shift; # default is in %pitch

    my %dsub_pitch =  ( 9 =>  2.74, 15 =>  2.74, 25 =>  2.76, 37 =>  2.76, ); # 15 pin in shell 2

    if (!defined($od)      ) { $od       = $ph * 2.2; }
    if (!defined($socket)  ) { $socket   = 0; }

    if (defined($rd)) {
	# use specified hole positions
	$rd       = 2.84;
	if (!defined($pitch)   ) {
	    $pitch = $dsub_pitch{$pins};
	    if (!defined($pitch)) { return -1; }
	}
	if (!defined($pin_name)) { $pin_name = [ ]; }

	my $gc = int( ($pins+1)/2 );
	my $lc = $pins - $gc;

	my $ix;
	my $px = $pitch;
	if ($socket) { $px = -$pitch; }
	my $mp = $lc / 2 + 1;
	#print "$pins $gc $lc $mp\n";
	for ($ix = 1; $ix <= $gc; $ix++) {
	    pin( ($mp-$ix)*$px, $rd/2, $ph, $od, $$pin_name[$ix]);
	}
	$mp -= 0.5;
	for ( ; $ix <= $pins; $ix++) {
	    pin( ($mp-($ix-$gc))*$px, -$rd/2, $ph, $od, $$pin_name[$ix]);
	}
    } else {
	# use dsub_pos supplied pin hole positions
	my $r = $dsub_pos{$pins};
	my $rx;
	my $pin = 1;
	for ($rx = 0; $rx < @$r; $rx++) {
	    my $px;
	    my $rr = $$r[$rx];
	    my $y = $$rr[0];
	    for ($px = 1; $px < @$rr; $px++) {
		my $x = $$rr[$px];
		if ($socket) { pin( -$x, $y, $ph, $od, $$pin_name[$pin]); }
		else         { pin(  $x, $y, $ph, $od, $$pin_name[$pin]); }
		$pin++;
	    }
	}
    }

}

sub dsub_mouting_holes($$ ; $$) {
    my $pins = shift;
    my $ph   = shift;

    my $od   = shift; # pin hole cu annulus diameter
    my $name = shift;

    if (!defined($od)  ) { $od       = $ph * 2.2; }
    if (!defined($name)) { $name = "FRAME_GND"; }

    my $w = $dsub_dim{C}[$dsub_sz{$pins}];;
    if (!defined($w)) { return -1; }
    my $x = $w / 2;

    # mounting holes
    pin( -$x, 0, $ph, $od, $name);
    pin(  $x, 0, $ph, $od, $name);
}

sub dsub_body($$ ; $$$) {
    my $pins = shift; # number of pins
    my $sz = shift;

    my $socket = shift; # undef or 0 for pins, else sockets

    # distandce from front plate to center line (between pin rows, where mounting holes are)
    # 0 = centered, < 0 is where mating plate is down (for config. where wider row is closest to pcb)
    # undef is straight connector
    my $cd = shift;

    # >0 stud height for an angled connector, 0 <= no studs, common values 5mm and 1/4"
    my $sh = shift;

    my $shell_sz = $dsub_sz{$pins};
    if (!defined($shell_sz)) { return -1; }
    if (ref($sz) ne "ARRAY") {
	$sz = [ $dsub_dim{A}[$shell_sz], $dsub_dim{E}[$shell_sz] ];
    }

    my $min;
    my $max;
    if (defined($cd)) {
	# angled connector (90°)
	# flange
	if ($cd == 0) {
	    # centered
	    $min = [ - $$sz[0]/2, - $$sz[1]/2 ];
	    $max = vec_add($min, $sz);
	} elsif ($cd < 0) {
	    $max = [ $$sz[0]/2, -$cd ];
	    $min = vec_sub($max, $sz);
	} else { # > 0
	    $min = [ - $$sz[0]/2, -$cd ];
	    $max = vec_add($min, $sz);
	}
	silk_rect( $min, $max, 0);

	my $w = $dsub_dim{C}[$shell_sz];
	if (!defined($w)) { return -1; }

	# http://www.dscc.dla.mil/Downloads/MilSpec/Docs/MIL-DTL-24308/dtl24308ss26.pdf p.1
	my $dw = 0.188 * 25.4; # width of stud

	# studs
	if (defined($sh) && $sh > 0) {
	    if ($cd < 0) { $sh = -$sh; }

	    silk_width(0.32);
	    silk_start($w/2 + $dw/2, -$cd);
	    silk_rline(0, -$sh);
	    silk_rline(-$dw, 0);
	    silk_rline(0,  $sh);
	    silk_width(0.18);
	    silk_start($w/2, -$cd);
	    silk_rline(0, -$sh);

	    silk_width(0.32);
	    silk_start(-$w/2 + $dw/2, -$cd);
	    silk_rline(0, -$sh);
	    silk_rline(-$dw, 0);
	    silk_rline(0,  $sh);
	    silk_width(0.18);
	    silk_start(-$w/2, -$cd);
	    silk_rline(0, -$sh);
	}

	# shroud
	my $mw; # mating shroud width
	if ($socket) {
	    $mw = $dsub_dim{Br}[$shell_sz] - 0.5; # 0.5 for the shroud thickness
	} else {
	    $mw = $dsub_dim{Bp}[$shell_sz] + 0.5;
	}
	my $mh = $dsub_dim{G}[$shell_sz]; # mating shroud height

	if ($cd < 0) { $mh = -$mh; }
	silk_width(0.32);
	silk_start($mw/2, -$cd);
	silk_rline(0, -$mh);
	silk_rline(-$mw, 0);
	silk_rline(0,  $mh);
    } else {
	# straight connector
	# flange
	$min = [ - $$sz[0]/2, - $$sz[1]/2 ];
	$max = vec_add($min, $sz);
	silk_rect( $min, $max, 1);

	# shroud
	my $B;
	my $D;
	my $r;
	if ($socket) {
	    $B = $dsub_dim{Br}[$shell_sz] - 0.5; # 0.5 for the shroud/silk thickness
	    $D = $dsub_dim{Dr}[$shell_sz] - 0.5;
	    $r = $dsub_Drradius;
	} else {
	    $B = $dsub_dim{Bp}[$shell_sz] + 0.5;
	    $D = $dsub_dim{Dp}[$shell_sz] + 0.5;
	    $r = $dsub_Dpradius;
	}

	my $tan10 = $dsub_sin10 / $dsub_cos10;
	my $r10   = [ $r * $dsub_cos10, - $r * $dsub_sin10 ];

	my $c1 = [ $B/2 - $r, $D/2 - $r ];
	my $ch = $D - 2*$r;
	my $c2 = vec_sub($c1, [ $ch * $tan10 , $ch ]);
	my $t1 = vec_add($c1, $r10);
	my $t2 = vec_add($c2, $r10);

	silk_start($$c1[0],  $D/2); # short line
	silk_line(-$$c1[0],  $D/2);
	silk_start($$c2[0], -$D/2); # long line
	silk_line(-$$c2[0], -$D/2);
	silk_start($$t1[0], $$t1[1]); # right side
	silk_line( $$t2[0], $$t2[1]);
	silk_start( -$$t1[0], $$t1[1]); # left side
	silk_line(  -$$t2[0], $$t2[1]);
	silk_circle($c1, $r, 90, 100);
	silk_circle($c2, $r, -90, -80);
	silk_circle(vec_xmirror($c1), $r, 90, -100);
	silk_circle(vec_xmirror($c2), $r, -90, 80);

    }
}

# for the names, element 0 is the name of the interface
my @dsub_rs232_name9  =
    qw/ rs232 DCD RxD TxD DTR GND DSR RTS CTS RI FRAME_GND FRAME_GND /;

# names from Table 8.1 in
#  Evi Nemeth, Garth Snyder, Scott Seebass, Trent R. Hein
#  Unix System Administration Handbook
#  Prentice Hall
my @dsub_rs232_name25 =
    qw/ rs232 FG TD RD RTS CTS DSR SG DCD pos neg n.a. SDCD SCTS STD TC SRD RC n.a. SRTS DTR SQ RI DRS SCTE BUSY /;

my %dsub_rs232_name = (
    9 => \@dsub_rs232_name9,
   25 => \@dsub_rs232_name25,
);

my @dsub_parport =
    qw/ pp nSTROBE Data0 Data1 Data2 Data3 Data4 Data5 Data6 Data7 nACK ~BUSY PaperEnd Select
	~nAutoLF nERROR nINIT ~nSelectIn GND GND GND GND GND GND GND GND /;

sub dsub_init() {
    dsub_pos(0);
}

dsub_init();

########################################
########################################
### GENERATE FOOTPRINT SECTION #########
########################################
########################################

sub gen_dsub_anon($$ ; $$$$) {
    my $pins = shift;
    my $socket = shift;
    my $sz = shift;
    my $cd = shift;
    my $name = shift;
    my $txt = shift;

    my $str = "pins";
    if ($socket) { $str = "socket"; }

    my $file = "dsub_$pins" . substr($str, 0, 1);
    if (ref($name) eq "ARRAY") { $file .= "_" . $$name[0]; }
    if (defined($txt)) { $file .= $txt; }
    $file .= ".fp";

    element_start($file,
"# Dsub $pins pin $str pcb 90°
# http://www.dscc.dla.mil/Downloads/MilSpec/Docs/MIL-DTL-24308/dtl24308.pdf
# shell receptable http://www.dscc.dla.mil/Downloads/MilSpec/Docs/MIL-DTL-24308/dtl24308ss23.pdf
# shell plug       http://www.dscc.dla.mil/Downloads/MilSpec/Docs/MIL-DTL-24308/dtl24308ss24.pdf
");

    dsub_mkpins($pins, 0.9, 2.0, $socket, $name);
    dsub_mouting_holes($pins, 3.2, 6);
    dsub_body($pins, $sz, $socket, $cd, 5);

    element_stop();
}
#gen_dsub_anon(25, 0, [ 53.1, 14.74 ], 11.6, \@dsub_parport, "_elfasale");
#gen_dsub_anon(25, 1, [ 53.1, 14.74 ], 11.6, \@dsub_parport, "_elfasale");

sub gen_TE_1734354_1() {
    element_start("te_1734354_1.fp",
"# Dsub 9pin socket pcb 90°
# http://www.te.com/commerce/DocumentDelivery/DDEController?Action=srchrtrv&DocNm=82068_AMPLIMITE_Right-Angle_Posted_Conn&DocType=Catalog+Section&DocLang=English&PartCntxt=
# http://www.te.com/commerce/DocumentDelivery/DDEController?Action=srchrtrv&DocNm=1734354&DocType=Customer+Drawing&DocLang=English&PartCntxt=1734354-1
# I'm usign RS232 pin names here, it woun't suit other uses
");

    dsub_mkpins(9, 1.0, 2.2, 1, \@dsub_rs232_name9, 2.84, 2.77);
    dsub_mouting_holes(9, 3.2, 6);
    dsub_body(9, [ 30.8, 12.4 ], 1, 8.08, 6);

    element_stop();
}
#gen_TE_1734354_1();

##############################
## mechanical stuff like enclosures

my @screw_data = (
    # BRB  bricka washer
    # M6S  sexkantskalle
    # MC6S insexskruv
    # M6M  mutter
    # M6M  flänsmutter
    # MCS  spårskruv
    # MRX  kryssskruv
    # MFS  försänkt spårskruv
    [ qw{ size   ID    BRB M6S MC6S  M6M  M6MF  MCS  MRX  MFS } ],
    [ qw{ M1.6   1.84   4   5   3.3  3.4   -    3.3  4.3  3.7 } ],
    [ qw{ M2     2.34   5   6   4.3  4.3   -    4.3  5    4.6 } ],
    [ qw{ M2.5   2.84   6   8   5    5.5   -    5    6    5.7 } ],
    [ qw{ M3     3.38   7   8   6    6     -    6    7    5.7 } ],
    [ qw{ M4     4.48   9  11   8    7.7   -    8    9    9.7 } ],
    [ qw{ M5     5.5   10  11  10    8.8  11.8 10   11   10.7 } ],
    [ qw{ M6     6.6   12  13  11   11.1  14.2 11   13   12.9 } ],
    [ qw{ M8     8.6   16  18  15   14.4  17.9 15   18   17.7 } ],
    [ qw{ M10   10.8   20  24  18   17.8  21.8 18   22   20.4 } ],
    [ qw{ M12   13.3   24  26  20   23.4  26                  } ],
    [ qw{ M16   17.3   30  33  26   26.8  34.5                } ],
    [ qw{ M20   21.3   37  40  33   33    42.8                } ],
    [ qw{ M24   25.3   44  48  40   39.6                      } ],
    [ qw{ M30   31.4   56  61  48   50.9                      } ],
    [ qw{ M36   37.6   66  71  57   60.8                      } ],
);
my %screw_data = ();
my %screw_hdr  = ();
my @screw_size = ();
{
    for (my $ix = 0; $ix < @screw_data; $ix++) {
	my @arr = @{$screw_data[$ix]};
	my $key = $arr[0];
	if ($ix == 0) {
	    $key = 'HDR';
	    for (my $cx = 2; $cx < @arr; $cx++) {
		$screw_hdr{$arr[$cx]} = $cx;
	    }
	} else {
	    push @screw_size, $arr[0];
	}
	my $val = [ @arr ];
	$screw_data{$key} = $val;
    }
}

sub screw($$$$;$$$) {
    my $xx = shift;
    my $yy = shift;
    my $sz  = shift; # e.g. M3 , key into %screw_data
    my $hdr = shift; # e.g. BRB, key into %screw_hdr

    my $name = shift // "1"; # pin name
    my $pin_number = shift // 1;
    my $support = shift // 0; # number of support holes

    my $data = $screw_data{$sz};
    my $col  = $screw_hdr{$hdr};

    my $hole = $$data[1];
    my $d_cu = $$data[$col];
    if (!defined($d_cu) || $d_cu eq "-" ) {
	return;
    }

    pin($xx, $yy, $hole, $d_cu, $name, "", $pin_number);
    if ($support > 0) {
	my $od = $d_cu;
	my $id = $hole;
	my $via_sz = 0.3;
	my $dr = ($od + $id)/4;
	my $ann = ($od - $id)/2;
	my $xdrill = int( 10 * $via_sz * $ann + 0.5 ) / 10;
	my $th = int( 5*($ann - $xdrill) + 0.5)/10;
	my $da = deg_rad(360 / $support);
	my $ds = deg_rad(270);
	#print STDERR "\t$xdrill $th / $dr $ann / $da $ds\n";
	for (my $sx = 0; $sx < $support; $sx++) {
	    my $a = $ds - $sx * $da;
	    my $x = $dr * cos($a);
	    my $y = $dr * sin($a);
	    pin($xx + $x, $yy + $y, $xdrill, $th,  $name, "", $pin_number);
	}
    }
}

sub gen_screws() {
    my $doc =
"# http://www.bufab.com/Portals/0/090330Teknikhandboken_72_dpi_090327.pdf
# p119: ID and BRB (washer) is from SS3576
# p120: mutterstorlekar, M6M SS-ISO 4032, M6MF SS-EN 1661
# p122: other values are from SS2173
";
    $round_first_pin = 1;
    for my $sz (@screw_size) {
	for my $hdr (sort keys %screw_hdr) {
	    my $cx = $screw_hdr{$hdr};
	    for my $support ( (0, 6, 12) ) {
		my $file;
		if ($support > 0) {
		    $file = sprintf "%s_%s_%02d.fp", $sz, $hdr, $support;
		} else {
		    $file = sprintf "%s_%s.fp", $sz, $hdr;
		}
		#print STDERR "\t$file\n";
		$pr_save = "";
		pr_inc();
		screw( 0, 0, $sz, $hdr, "1", 1, $support);
		my $body = $pr_save;
		pr_dec();
		if ($body) {
		    element_start($file, $doc);
		    pr($body, 1);
		    element_stop();
		}
	    }
	}
    }
    $round_first_pin = 0;
}
#gen_screws();

sub gen_Hammond_1455C801() {
    my $file = "Hammond_1455C801.fp";
    my $doc = "# https://www.hammfg.com/files/parts/pdf/1455C801BK.pdf";
    element_start($file, $doc);
    my $xx = 50;
    my $yy = 79;
    silk_crect($origin, [$xx,$yy], 0);

    my $dx = 3.55;
    silk_width(0.12);

    silk_start(-$xx/2 + $dx, -$yy/2);
    silk_rline(0, $yy);

    silk_start( $xx/2 - $dx, -$yy/2);
    silk_rline(0, $yy);
    element_stop();
    silk_width();
}
#gen_Hammond_1455C801();

sub gen_Hammond_70009() {
    my $name = "Hammond_70009";
    my $doc = "# http://www.hammondmfg.com/pdf/70009.pdf";

    my $outer = 92;
    my $screw = 79.5/2;
    my $screw_r = 3.4/2;
    my $top = 87/2;
    my $bot = 85.17/2;
    my $radi = 12.5; # inside corner radius
    my $side = 66/2;

    my $gap = $bot - $side;
    # [ bot + dx, bot + dx ] = corner center
    # sqrt( (dx + gap)^2 + dx^2) = corner_r
    # dx^2 + 2*gap*dx + gap^2 + dx^2 = corner_r^2
    # 2*dx^2 + 2*2*gap/2*dx = corner_r^2 - gap^2
    # dx^2 + 2*gap/2*dx + (gap/2)^2 =
    #  (dx + gap/2)^2 =
    #  (corner_r^2 - gap^2)/2 + (gap/2)^2

    # dx + gap/2 = sqrt( (corner_r^2 - gap^2)/2 + (gap/2)^2 )
    # dx =
    #   sqrt( (corner_r^2 - gap^2)/2 + (gap/2)^2 ) - gap/2
    #   sqrt( corner_r^2/2 - gap^2/2 + gap^2/4 ) - gap/2
    #   sqrt( corner_r^2/2 - gap^2/4 ) - gap/2

    my $dx = sqrt( $radi*$radi/2 - $gap*$gap/4 ) - $gap/2;
    my $corner = $bot + $dx;
    my $angle = rad_deg( atan2($dx, $gap+$dx) );
    my $sweep = 90 - 2*$angle;
    #print "$side $gap $bot $dx $angle $sweep\n";

    {
	$pr_save = "";
	pr_inc();
	silk_width(0.12);

	# enclosure outside
	silk_crect($origin, [$outer,$outer], 1);

	pr("# enclosure lid mounting holes\n");
	silk_circle([-$screw,-$screw], $screw_r);
	silk_circle([ $screw,-$screw], $screw_r);
	silk_circle([-$screw, $screw], $screw_r);
	silk_circle([ $screw, $screw], $screw_r);

	silk_width();

	pr("# enclosure inside straight sides\n");
	silk_start(-$bot, -$side);
	silk_line (-$bot,  $side);

	silk_start(-$side, $bot);
	silk_line ( $side, $bot);

	silk_start( $bot,  $side);
	silk_line ( $bot, -$side);

	silk_start( $side, -$bot);
	silk_line (-$side, -$bot);

	pr("# enclosure inside corners\n");
	silk_arc([-$corner,-$corner], $radi,  90+$angle, $sweep);
	silk_arc([-$corner, $corner], $radi, 180+$angle, $sweep);
	silk_arc([ $corner, $corner], $radi, 270+$angle, $sweep);
	silk_arc([ $corner,-$corner], $radi,     $angle, $sweep);

	pr_dec();
    }
    my $body = $pr_save;
    my $file;

    # without mouting holes
    $file = "$name.fp";
    element_start($file, $doc);
    pr($body,1);
    element_stop();

    # with pcb mounting holes
    my $id = 3.5;
    my $od = 8;
    my $amaj = int($bot) - 5;
    my $amin = int($side) - 5;

    $file = "${name}_a.fp";
    element_start($file, $doc);
    pr($body,1);
    pr("# pcb mounting holes\n");
    pin(-$amaj,-$amin, $id, $od, "mnt", undef, 1);
    pin(-$amaj, $amin, $id, $od, "mnt", undef, 1);
    pin( $amaj, $amin, $id, $od, "mnt", undef, 1);
    pin( $amaj,-$amin, $id, $od, "mnt", undef, 1);
    element_stop();

    # dito with mounting holes for the enclosure
    $file = "${name}_b.fp";
    element_start($file, $doc);
    pr($body,1);
    pr("# pcb mounting holes\n");
    pin(-$amaj,-$amin, $id, $od, "mnt", undef, 1);
    pin(-$amaj, $amin, $id, $od, "mnt", undef, 1);
    pin( $amaj, $amin, $id, $od, "mnt", undef, 1);
    pin( $amaj,-$amin, $id, $od, "mnt", undef, 1);
    pr("# enclosure mounting hole cutout\n");
    silk_cross(-$amaj, 0, 5);
    silk_start(-$bot, -5);
    silk_rline(5, 0);
    silk_arc([-$amaj, 0], 5, 90, 180);
    silk_start(-$bot, 5);
    silk_rline(5, 0);
    #
    silk_cross( $amaj, 0, 5);
    silk_start( $bot, -5);
    silk_rline(-5, 0);
    silk_arc([ $amaj, 0], 5, 270, 180);
    silk_start($bot, 5);
    silk_rline(-5, 0);
    #
    element_stop();

    # dito antother version
    $file = "${name}_c.fp";
    element_start($file, $doc);
    pr($body,1);
    pr("# pcb mounting holes\n");
    pin(-$amaj,-$amin, $id, $od, "mnt", undef, 1);
    pin(-$amaj, $amin, $id, $od, "mnt", undef, 1);
    pin( $amaj, $amin, $id, $od, "mnt", undef, 1);
    pin( $amaj,-$amin, $id, $od, "mnt", undef, 1);
    pr("# enclosure mounting hole cutout\n");
    pin(-$amaj, 0, 4, 10, "mnt", undef, 1);
    pin( $amaj, 0, 4, 10, "mnt", undef, 1);
    #
    element_stop();

}
#gen_Hammond_70009();

sub gen_Hammond_1590ZGRP() {
    my $name = "Hammond_";
    my $family = "# https://www.hammfg.com/electronics/small-case/plastic/1590zgrp.pdf\n";
    my $data = " from dimensioned drawings https://www.hammfg.com/files/parts/pdf/<part_no>.pdf     lid screw and inner panel screw have the same size (except length)
             outer dim     lid screws       heigh/outer/inner/lid  inside dim max/mnt/min x/y                  panel max/mnt/min/cutout x/y                           screw mntdim  midcutout
1590ZGRP081  80.00  75.00  4  68.00  61.72   55.00  47.30 11.30     70.42  67.90  54.92   65.97  45.00  32.20   68.00  60.00  53.00  7.50   63.00   0.00  26.00 18.50 M4  7.60 4.70
1590ZGRP082 110.00  75.00  4  98.00  62.60   55.00  46.40 10.40     99.92  98.00  85.39   65.97  45.00  32.23   97.00  89.00  82.00  7.50   62.00   0.00  29.00 16.50 M4  7.44 4.80
1590ZGRP083 160.00  75.00  4 148.00  63.00   55.00  47.50 11.30    150.71 148.00 134.71   64.62  45.00  32.28  148.50 139.00 133.50  7.50   63.00   0.00  30.00 16.50 M4  7.60 4.80
1590ZGRP084  80.50  75.50  4  68.00  63.00   75.00  67.45 11.20     70.98  68.00  56.85   66.05  45.00  34.30   68.00  60.00  53.00  7.50   63.00   0.00  26.00 18.50 M4  7.65 5.00
1590ZGRP121 122.00 120.00  4 106.00 104.00   90.20  80.85 20.25    113.27 106.00  89.97  110.11  82.00  65.97  108.00  95.00  86.00 11.00  107.00  26.00  61.00 23.00 M6 10.21 6.80

# inner min is not shown, we have 196.37 which seems to be inside -- mounting hole, use ixmin = 196.37 - (204 - 196.37) = 188.74
1590ZGRP123 220.00 120.00  4 204.00 104.00   90.50  80.60 20.00    211.47 204.00 188.74  111.67  82.00  65.69  205.00 193.00 185.00 10.00  104.60  26.00  60.60 22.00 M6 10.49 6.79

# inner min is not shown, we have 171.48 which seems to be inside -- mounting hole, use ixmin = 171.48 - (178.20 - 171.48) = 164.76
1590ZGRP131 190.15  75.00  4 178.30  63.00   55.00  47.80 11.30    181.17 178.20 164.76   65.67  44.80  31.70  178.50 169.00 162.50  8.00   63.00   0.00  30.00 16.50 M4  7.05 4.60

1590ZGRP161 160.00 160.00  4 140.00 140.00   90.30  79.25 15.00    147.76 140.00 119.43  147.76 110.00  89.27  142.50 132.00 114.50 14.00  142.00  38.00  84.00 29.00 M6  9.98 6.80
1590ZGRP162 260.00 160.00  4 240.00 140.00   90.00  79.20 15.20    248.56 240.00 220.96  148.96 110.00  90.96  243.00 233.00 215.00 14.00  143.00  38.00  85.00 29.00 M6 11.11 6.80
1590ZGRP163 360.00 160.00  4 340.00 140.00   90.00  78.50 14.50    345.97 340.00 317.99  145.79 110.00  88.08  344.00 332.00 315.81 14.10  144.00  38.00  86.32 28.84 M6 10.31 6.50
1590ZGRP233 200.00 250.00  4 180.00 230.00  120.10 109.00 20.00    186.96 180.00 160.26  236.96 200.00 178.71  184.00 173.00 156.00 14.00  234.00  50.00 174.00 30.00 M6 10.43 6.60
1590ZGRP234 255.00 250.00  4 235.00 232.11  120.25 109.10 20.00    243.06 235.00 215.06  237.56 199.50 179.56  238.00 227.00 208.00 15.00  232.00  50.00 174.00 29.00 M6 10.55 6.80
1590ZGRP235 255.00 250.00  4 234.87 229.20  160.50 149.10 60.00    243.06 235.00 215.06  237.56 199.50 179.56  238.00 227.00 208.00 15.00  232.00  50.00 174.00 29.00 M6 10.55 6.80
1590ZGRP243 400.00 250.00  4 380.13 229.20  120.25 109.20 20.00    386.10 380.00 359.36  234.76 200.00 174.94  382.00 372.00 352.00 15.00  232.00  50.00 174.00 29.00 M6 10.63 6.80
1590ZGRP244 400.00 250.00  4 380.00 229.20  160.00 149.20 60.00    385.85 380.00 357.76  235.26 200.00 177.87  382.00 372.00 352.00 15.00  232.00  50.00 174.00 29.00 M6 10.63 6.80

# mounting hole y c-c, shown is lid hole -- mnt hole, use iymnt = 370.00 - (385.00 - 370.00) = 355.00
1590ZGRP253 400.00 405.00  4 380.00 385.00  120.00 109.10 20.00    388.07 380.00 360.07  393.07 355.00 335.07  383.00 373.03 354.60 14.20  388.00 125.00 329.60 29.20 M6 10.56 6.30

# lid x in drawing is from center, so screw-screw = 2* 290
1590ZGRP263 600.00 250.00  6 580.00 229.20  120.00 108.50 20.00    586.06 580.00 557.98  235.98 200.00 178.08  582.65 573.00 553.64 14.50  232.64  50.00 174.63 29.01 M6 10.70 6.80 28.58 16.69 208.38
1590ZGRP264 600.00 250.00  6 580.00 229.20  160.00 148.50 60.00    586.06 580.00 557.98  235.98 200.00 178.08  582.65 573.00 553.64 14.50  232.64  50.00 174.63 29.01 M6 10.70 6.80 28.58 16.69 209.96
";

    my @data = grep m/^1590/, split(/\n/, $data);
    my $pfx = "https://www.hammfg.com/files/parts/pdf";

    for my $line (@data) {
	my ($part, $tx, $ty,  $ls, $lx, $ly,  $ho, $hi, $hl,
	    $ixmax, $ixmnt, $ixmin,  $iymax, $iymnt, $iymin,
	    $pxmax, $pxmnt, $pxmin, $pxcut,  $pymax, $pymnt, $pymin, $pycut, $screw,
	    $smnto, $smnti, $pmidx, $pmidy, $imid)
	    = split(/[ \t]+/, $line);
	my $file = $name . $part;
	my $doc = $family . "# $pfx/$file.pdf\n";

	element_start($file . ".fp", $doc);

	pr("# enclosure outside\n");
	silk_width(0.12);
	{
	    my $outer = [ $tx, $ty ];
	    my $ld = $tx - $lx;
	    if ($ld > $ty - $ly) { $ld = $ty - $ly; }
	    silk_crect($origin, $outer, $ld/2);
	}

	pr("# mounting holes\n");
	{
	    my @silk_circle = (
		# mounting holes
		[ $smnto/2, [ $ixmnt/2 ], [ $iymnt/2 ] ],
		[ $smnti/2, [ $ixmnt/2 ], [ $iymnt/2 ] ],
	    );
	    # lid holes
	    if ($ls == 4) {
		push @silk_circle, [ $ls/2, [ $lx/2 ], [ $ly/2 ] ];
	    } elsif ($ls == 6) {
		push @silk_circle, [ $ls/2, [ 0, $lx/2 ], [ $ly/2 ] ];
	    }
	    iterate_fdxy(\&silk_circle, @silk_circle);
	}

	pr("# inner outline\n");
	silk_width();
	{
	    my $in = [ $ixmax/2, $iymax/2 ];
	    my $mc = [ $ixmnt/2, $iymnt/2 ];
	    my $ir = 3;
	    my $mr = $$mc[0] - $ixmin/2;
	    my $xposts;
	    if ($ls == 6) {
		$xposts = [ $$in[1] - $imid/2, $ly/2, 0 ];
	    }
	    box_inside_path($in, $mc, $mr, $ir, $xposts);
	}

	pr("# steel inner panel\n");
	silk_width(0.18);
	{
	    my $pin = [$pxmax/2, $pymax/2];
	    my $pmc = [$pxmax/2, $pymin/2 + $pxcut];
	    my $pmr = $pxcut;
	    my $xposts;
	    if ($ls == 6) {
		$xposts = [ $pmidx/2, $pymax/2 - $pmidy + $pmidx/2, 0 ];
	    }
	    box_inside_path($pin, $pmc, $pmr, 0, $xposts);
	}

	pr("# steel inner panel mounting holes\n");
	$round_first_pin = 1;
	{
	    my $id = $screw_data{$screw}->[1];
	    my $od = $screw_data{$screw}->[2]; # use BRB's size
	    pin(-$pxmnt/2,0, $id, $od, undef, undef, 1);
	    pin( $pxmnt/2,0, $id, $od, undef, undef, 1);
	    if ($pymnt != 0) {
		pin(-$pxmnt/2, -$pymnt, $id, $od, undef, undef, 1);
		pin(-$pxmnt/2,  $pymnt, $id, $od, undef, undef, 1);
		pin( $pxmnt/2, -$pymnt, $id, $od, undef, undef, 1);
		pin( $pxmnt/2,  $pymnt, $id, $od, undef, undef, 1);
	    }
	}

	element_stop();

	if ($part eq "1590ZGRP082") {
	    for my $num ((2,4)) {
		element_start($file . "_$num.fp", $doc);

		pr("# enclosure outside\n");
		silk_width(0.12);
		{
		    my $outer = [ $tx, $ty ];
		    my $ld = $tx - $lx;
		    if ($ld > $ty - $ly) {
			$ld = $ty - $ly;
		    }
		    silk_crect($origin, $outer, $ld/2);
		}

		pr("# mounting holes\n");
		{
		    my @silk_circle = (
			# mounting holes
			[ $smnto/2, [ $ixmnt/2 ], [ $iymnt/2 ] ],
			[ $smnti/2, [ $ixmnt/2 ], [ $iymnt/2 ] ],
		    );
		    # lid holes
		    if ($ls == 4) {
			push @silk_circle, [ $ls/2, [ $lx/2 ], [ $ly/2 ] ];
		    } elsif ($ls == 6) {
			push @silk_circle, [ $ls/2, [ 0, $lx/2 ], [ $ly/2 ] ];
		    }
		    iterate_fdxy(\&silk_circle, @silk_circle);
		}

		pr("# inner outline\n");
		silk_width();
		{
		    my $in = [ $ixmax/2, $iymax/2 ];
		    my $mc = [ $ixmnt/2, $iymnt/2 ];
		    my $ir = 3;
		    my $mr = $$mc[0] - $ixmin/2;
		    my $xposts;
		    if ($ls == 6) {
			$xposts = [ $$in[1] - $imid/2, $ly/2, 0 ];
		    }
		    box_inside_path($in, $mc, $mr, $ir, $xposts);
		}

		pr("# steel inner panel mounting holes\n");
		$round_first_pin = 1;
		{
		    my $id = $screw_data{$screw}->[1];
		    my $od = $screw_data{$screw}->[2]; # use BRB's size
		    pin(-$pxmnt/2,0, $id, $od, undef, undef, 1);
		    pin( $pxmnt/2,0, $id, $od, undef, undef, 1);
		}
		pr("# bottom mounting holes\n");
		{
		    my $id = $screw_data{"M3"}->[1];
		    my $od = $screw_data{"M3"}->[2]; # use BRB's size
		    my @list;
		    if ($num == 4) { @list = (-72.4/2, -32/2, 32/2, 72.4/2); }
		    else { @list = (-32/2, 32/2); }
		    for my $xp (@list) {
			pin($xp,0, $id, $od, undef, undef, 1);
		    }
		}

		element_stop();
	    }
	}

	$round_first_pin = 0;
	silk_width();
    }
}
#gen_Hammond_1590ZGRP();

sub gen_spelsberg_2k12_top() {
    element_start("spelsberg_2k12_top.fp",
"# plastic junction box Swedish E-14 375 81, cover
");
    my $we = 85.5;
    my $wi = 74.3;
    my $ri =  3;
    my $re = $ri + ($we - $wi)/2;
    my $min = [ -$we/2 + 6, -$we/2 +6 ];
    my $max = vec_add($min, [ 24, 18 ]);

    silk_width(0.12);
    silk_sq($we, $re);
    silk_rect($min, $max, 1);
    silk_start(-4, -$we/2);
    silk_line( -4,  $we/2 - 21);
    silk_line(-25,  $we/2);
    silk_start( 4, -$we/2);
    silk_line(  4,  $we/2 - 21);
    silk_line( 25,  $we/2);

    silk_width(0.32);
    silk_sq($wi, $ri);

    my $a = 30;
    my $b = 10;
    $round_first_pin = 1;
    pin( -$a, -$b, 3.5, 7);
    use_same_pin_no();
    pin(  $a, -$b, 3.5, 7);
    use_same_pin_no();
    pin( -$a,  $a, 3.5, 7);
    use_same_pin_no();
    pin(  $a,  $a, 3.5, 7);
    $round_first_pin = 0;

    element_stop();
}
sub gen_spelsberg_2k12_bottom() {
    element_start("spelsberg_2k12_bottom.fp",
"# plastic junction box Swedish E-14 375 81, bottom (or base)
");

    #TODO

    element_stop();
}
#gen_spelsberg_2k12_top();
#gen_spelsberg_2k12_bottom();

sub gen_150xboard( $ ) {
    my $h = shift;
    element_start("150x${h}board.fp", "# a simple board with some mounting holes\n");
    $round_first_pin = 1;
    my $w = 150;
    my $s = 10;
    my $x = $w/2 - $s;
    my $y = $w/2 - $s;

    pin( -$x, -$y, 4.5, 11);
    use_same_pin_no();
    pin(   0, -$y, 4.5, 11);
    use_same_pin_no();
    pin(  $x, -$y, 4.5, 11);
    use_same_pin_no();

    pin( -$x,  0 , 4.5, 11);
    use_same_pin_no();
    pin(  $x,  0 , 4.5, 11);
    use_same_pin_no();

    pin( -$x,  $y, 4.5, 11);
    use_same_pin_no();
    pin(   0,  $y, 4.5, 11);
    use_same_pin_no();
    pin(  $x,  $y, 4.5, 11);

    silk_start(-$w/2, -$w/2);
    silk_rline( 0 ,  $h);
    silk_rline( $w,   0);
    silk_rline( 0 , -$h);
    silk_rline(-$w,   0);
    element_stop();
}
#gen_150xboard(160);

sub fibox_mnx_supportH( $$ ) {
    my $x = shift;
    my $y = shift;

    my $a = mk_mm($x-10);
    my $b = mk_mm($x+10);
    my $c = mk_mm($y);
    pr("ElementArc [ $a $c 1mm 1mm 0 360 0.32mm ]\n");
    pr("ElementArc [ $b $c 1mm 1mm 0 360 0.32mm ]\n");
}
sub fibox_mnx_supportV( $$ ) {
    my $x = shift;
    my $y = shift;

    my $a = mk_mm($y-10);
    my $b = mk_mm($y+10);
    my $c = mk_mm($x);
    pr("ElementArc [ $c $a 1mm 1mm 0 360 0.32mm ]\n");
    pr("ElementArc [ $c $b 1mm 1mm 0 360 0.32mm ]\n");
}
sub fibox_mnx_screw($$) {
    my $x = shift;
    my $y = shift;

    pin( $x, $y, 4.5, 10, "", "");
    use_same_pin_no();
}
sub gen_fibox_mnx( @ ) {
    my $size = shift;

    my $ox = shift; # outer dims.
    my $oy = shift;

    my $mx = shift; # mounting holes
    my $my = shift;

    my $Px = shift; # pcb major dims
    my $Py = shift;

    my $px = shift; # pcb major dims
    my $py = shift;

    my $sH = shift;
    my $sV = shift;

    element_start("fibox_mnx_$size.fp", "#
# http://www.fibox.se/documents/tuoteluettelo/2012/FIBOX_2012_Catalogues_swe_web.pdf
# http://www.fibox.com/documents/tuoteluettelo/2012/FIBOX_2012_Catalogues_eng_web.pdf
# Note: silk have enclosure dimension, pcb must be smaller
# Screw holes are 4.5 or 3.5mm (low base, h=25mm)
# Support pins not in low base (h=25mm) enclosures
");

    # outer dims
    pr("# outside dimensions\n");
    silk_start( $ox/2, $oy/2);
    silk_rline( -$ox,    0);
    silk_rline(    0, -$oy);
    silk_rline(  $ox,    0);
    silk_rline(    0,  $oy);

    # mounting holes, to mount the enclosure
    {
	my $l = 5;
	pr("# mounting holes\n");
	silk_cross( $mx/2, $my/2, $l);
	silk_cross(-$mx/2, $my/2, $l);
	silk_cross( $mx/2,-$my/2, $l);
	silk_cross(-$mx/2,-$my/2, $l);
    }

    # enclusure internal outline
    {
	my $dx = ($Px - $px)/2;
	my $dy = ($Py - $py)/2;

	pr("# inside outline, pcb has to be smaller\n");
	silk_start(  $px/2, $Py/2);
	silk_rline( -$px,    0);
	silk_rline(    0, -$dy);
	silk_rline( -$dx,    0);
	silk_rline(    0, -$py);
	silk_rline(  $dx,    0);
	silk_rline(    0, -$dy);
	silk_rline(  $px,    0);
	silk_rline(    0,  $dy);
	silk_rline(  $dx,    0);
	silk_rline(    0,  $py);
	silk_rline( -$dx,    0);
	silk_rline(    0,  $dy);
    }

    # support pins
    pr("# support studs (not in low base, h=25mm, enclosures)\n");
    iterate_y_xxx(\&fibox_mnx_supportH, $sH);
    iterate_y_xxx(\&fibox_mnx_supportV, $sV);

    # screw holes, to mount the pcb into the enclosure
    pr("# pcb mouinting holes (3.5mm in low bases, h=25mm)\n");
    pr("# if you don't use/need all supports, copy file and remove relevant lines\n");
    for my $r (@_) { iterate_y_xxx(\&fibox_mnx_screw, $r); }
    if ($size eq "360x255") {
	# for some reason theese are not symmetric around y-centerline
	fibox_mnx_screw( -40, -35/2);
	fibox_mnx_screw( -40,  35/2);
    }

    element_stop();
}
sub gen_fibox_mnx_all() {
    my @arr = (
	[
	    "100x100",  100, 100,  83.5, 83.5,  89.2, 89.2,  65, 65,
	    [ ], [ ], # horisotal studs, vertical studs
	    [ 70, 0, 45 ], # [ y, x1, x2, ... ]
	],
	[
	    "130x80",  130, 80,  113.5, 63.5,  121, 71,  95.5, 45.5,
	    [ 40, 0 ], [ 0, 90 ],
	    [ 0, 90 ], [ 40, 0, 75],
	],
	[
	    "130x130",  130, 130,  113.5, 113.5,  121, 121,  95.5, 95.5,
	    [ 90, 0 ], [ 0, 90 ],
	    [ 0, 90 ], [ 90, 0, 75 ],
	],
	[
	    "180x130",  180, 130,  163.5, 113.5,  171, 121,  145, 95.5,
	    [ 90, 0 ], [ 0, 140],
	    [ 0, 140 ], [ 90, 0, 100 ],
	],
	[
	    "180x180",  180, 180,  163.5, 163.5,  171, 171,  145, 145,
	    [ 140, 0 ], [  0, 140 ],
	    [ 0, 140 ], [ 100, 140 ], [ 140, 0, 100 ],
	],
	[
	    "255x180",  255, 180,  238.5, 163.5,  246, 171,  220, 145,
	    [ 139, 0 ], [ 0, 215 ],
	    [ 0, 215 ], [ 100, 35, 215 ], [ 139, 0, 125, 201.6 ],
	],
	[ # I guess the pcb dimensions
	    "360x255",  360, 255,  305, 266.5,  349.6, 246,  323.6, 220,
	    [ 215, 180 ], [ 0, 320 ],
	    [ 0, 41, 320 ], [ 35, 280 ], [ 125, 41, 320 ],
	    [ 201.6, 41, 320 ], [ 215, 80, 180, 280 ],
	],
    );

    for my $r (@arr) {
	gen_fibox_mnx( @$r );
    }
}
#gen_fibox_mnx_all();

sub gen_box_pcb_mounting_holes($$$) {
    my $r = shift;
    my $id = @$r[0];
    my $od = @$r[1];
    my $x = shift;
    my $y = shift;

    $round_first_pin = 1;
    pin( $x, $y, $id, $od, "", "");
    use_same_pin_no();
}
sub gen_box_pcb_cstandoff($$$) {
    my $r = shift;
    my $sw  = @$r[0];
    my $dia = @$r[1];
    my $x   = shift;
    my $y   = shift;

    silk_width($sw);
    silk_arc( [$x, $y], $dia/2,  0, 360);
    silk_width();
    use_same_pin_no();
}
sub gen_box_pcb_rstandoff($$$) {
    my $r = shift;
    my $sw  = @$r[0];
    my $xw  = @$r[1];
    my $yw  = @$r[2];
    my $x   = shift;
    my $y   = shift;

    silk_width($sw);
    silk_crect([$x, $y], [$xw, $yw], 0);
    silk_width();
    use_same_pin_no();
}

sub twoCircles($$$) {
    # all dims. relative center of circle A
    # given booth radi and circle B's limit to the right (xe)
    # find circle B's center and possble cicle touching angle

    # the idea is that a line is coming down, striking the left edge of A
    # following its border clockwise till it takes away following a horizontal
    # trajectory to the overside of B, rounding it, and goes straight down

    my $Ar = shift;
    my $Br = shift;
    my $xe = shift;

    my $shape = 0;

    # X and Y-distance of B to A
    # center of B is then [ dx, dy ]
    my $dx = $xe - $Br;
    my $dy;

    # angle of contact between A anb B relative the vertical
    # limits are: 0 is straight down, 90 is to the left
    my $da;

    if ($dx <= - ($Ar + $Br)) {
	# Circle A doen't interract with B
	$dy = undef;
	$da = undef;
	$shape = 0;
    } elsif ($dx < 0) {
	# B right end is below A and
	#  between A left edge and B center to the left of A center
	# find B's dy so that A and B touches
	my $cc = $Ar + $Br; # center to center dist.
	$dy = sqrt($cc*$cc - $dx*$dx); # dito, Y-vise
	$da = sprintf( "%.3f", Acos($dy / $cc));
	$shape = 1;
    } elsif ($dx == 0) {
	# A and B are vertically aligned
	$dy = $Ar + $Br;
	$da = 0;
	$shape = 2;
    } else {
	# A bottom and B top are horizontally aligned
	# there is a horizontal line between the arcs
	$dy = $Ar + $Br;
	$da = 0;
	$shape = 3;
    }
    #print "Ar: $Ar, Br: $Br, xe: $xe, sh: $shape, dx: $dx, dy: $dy, da: $da\n";

    ( $shape, [ $dx, $dy ], $da );
}

# TODO: add x/y-center mounting posts
sub box_inside_path($$$;$$$) {
    # mounting holes on the right/left side
    my $in = shift; # [ x, y ] major inner x and y extent
    my $mc = shift; # [ x, y ], mounting hole center

    my $mr = shift; # arc protruding into the interiour dut to the mounting hole
    my $ir = shift // 1; # small inside inner radi

    my $xposts = shift; # [ r, y, x... ] on booth top and bottom side
    my $yposts = shift; # [ r, x, y... ] dito left/right

    my ($ix, $iy) = @$in;

    my ( $Rshape, $rc, $Ra ) = twoCircles($mr, $ir, $$in[0] - $$mc[0]);
    my ( $Bshape, $bc, $Ba ) = twoCircles($mr, $ir, $$in[1] - $$mc[1]);
    my ( $Xshape, $Xc, $Xa );
    my ( $Yshape, $Yc, $Ya );
    my $Rb = 90 - $Ra;
    my $Bb = 90 - $Ba;
    my $Xb;
    my $Yb;

    my ( $xr, $xy, $yr, $yx, @xlist, @ylist );

    if ($xposts) {
	( $Xshape, $Xc, $Xa ) = twoCircles($$xposts[0], $ir, $$in[1] - $$xposts[1]);
	$Xb = 90 - $Xa;
	$xr = shift @$xposts;
	$xy = shift @$xposts;
	@xlist = sort { $a <=> $b } @$xposts;
	my @rev = map { -$_ } reverse @xlist;
	if ($xlist[0] == 0) { shift @xlist; } # to avoid duplicates
	@xlist = (@rev, @xlist);
    }
    if ($yposts) {
	( $Yshape, $Yc, $Ya ) = twoCircles($$yposts[0], $ir, $$in[0] - $$yposts[1]);
	$Yb = 90 - $Ya;
	$yr = shift @$yposts;
	$yx = shift @$yposts;
	@ylist = sort { $a <=> $b } @$yposts;
	my @rev = map { -$_ } reverse @ylist;
	if ($ylist[0] == 0) { shift @ylist; } # to avoid duplicates
	@ylist = (@rev, @ylist);
    }

    if ($Rshape == 0 || $Bshape == 0) {
	silk_crect($origin, vec_mul(2,$in), $ir);
	return;
    }


    # clockvise from top left
    if ($ir) { silk_circle([ -$$mc[0] + $$bc[1], -$$in[1] + $ir], $ir, 270, $Bb); }
    if ($Bshape == 3) {
	silk_start(-$$mc[0] + $mr, -$$in[1] + $ir);
	silk_line (-$$mc[0] + $mr, -$$mc[1]);
    }
    if ($mr) { silk_circle( [-$$mc[0], -$$mc[1]], $mr, 180-$Ba, -$Rb+$Ba); }
    if ($Rshape == 3) {
	silk_start(-$$mc[0]          , -$$mc[1] + $$rc[1] - $ir);
	silk_line (-$$mc[0] - $$rc[0], -$$mc[1] + $$rc[1] - $ir);
    }
    if ($ir) { silk_circle([ -$$mc[0] - $$rc[0], -$$mc[1] + $$rc[1]], $ir, 270+$Ra, $Rb); }

    # left line
    silk_start(-$$in[0], -$$mc[1]+$$rc[1]);
    if ($yposts) {
	for my $ty (@ylist) {
	    silk_line ( -$$in[0], $ty - $$Yc[1] );
	    if ($ir) { silk_circle([ -$$in[0] + $ir, $ty - $$Yc[1] ], $ir, 0, $Yb); }
	    if ($Yshape == 3) {
		silk_start(-$$in[0]+$ir, $ty - $$Yc[1] + $ir);
		silk_line (-$yx        , $ty - $$Yc[1] + $ir);
	    }
	    if ($yr) { silk_circle([ -$yx,  $ty], $yr, 270-$Ya, -2*$Yb); }
	    if ($Yshape == 3) {
		silk_start(-$yx        , $ty + $$Yc[1] - $ir);
		silk_line (-$$in[0]+$ir, $ty + $$Yc[1] - $ir);
	    }
	    if ($ir) { silk_circle([ -$$in[0] + $ir, $ty + $$Yc[1] ], $ir, 270+$Ya, $Yb); }
	    silk_start( -$$in[0], $ty + $$Yc[1] );
	}
    }
    silk_line (-$$in[0], +$$mc[1]-$$rc[1]);

    # left bottom
    if ($ir) { silk_circle([ -$$mc[0] - $$rc[0], $$mc[1] - $$rc[1]], $ir, 0, $Rb); }
    if ($Rshape == 3) {
	silk_start(-$$mc[0] - $$rc[0],  $$mc[1] - $$rc[1] + $ir);
	silk_line (-$$mc[0]          ,  $$mc[1] - $$rc[1] + $ir);
    }
    if ($mr) { silk_circle( [-$$mc[0],  $$mc[1]], $mr, 270-$Ra, -$Rb+$Ba); }
    if ($Bshape == 3) {
	silk_start(-$$mc[0] + $mr,  $$mc[1]);
	silk_line (-$$mc[0] + $mr,  $$in[1] - $ir);
    }
    if ($ir) { silk_circle([ -$$mc[0] + $$bc[1],  $$in[1] - $ir], $ir, 0+$Ba, $Bb); }

    # bottom line
    silk_start(-$$mc[0]+$$bc[1],  $$in[1]);
    if ($xposts) {
	for my $tx (@xlist) {
	    silk_line ( $tx - $$Xc[1], $$in[1]);
	    if ($ir) { silk_circle([ $tx - $$Xc[1],  $$in[1] - $ir], $ir, 90, $Xb); }
	    if ($Xshape == 3) {
		silk_start($tx - $$Xc[1] + $ir,  $$in[1]-$ir);
		silk_line ($tx - $$Xc[1] + $ir,  $xy);
	    }
	    if ($xr) { silk_circle([ $tx,  $xy], $xr, -$Xa, -2*$Xb); }
	    if ($Xshape == 3) {
		silk_start($tx + $$Xc[1] - $ir,  $xy);
		silk_line ($tx + $$Xc[1] - $ir,  $$in[1]-$ir);
	    }
	    if ($ir) { silk_circle([ $tx + $$Xc[1],  $$in[1] - $ir], $ir, $Xa, $Xb); }
	    silk_start( $tx + $$Xc[1], $$in[1]);
	}
    }
    silk_line ( $$mc[0]-$$bc[1],  $$in[1]);

    # bottom right
    if ($ir) { silk_circle([  $$mc[0] - $$bc[1],  $$in[1] - $ir], $ir, 90, $Bb); }
    if ($Bshape == 3) {
	silk_start( $$mc[0] - $mr,  $$in[1] - $ir);
	silk_line ( $$mc[0] - $mr,  $$mc[1]);
    }
    if ($mr) { silk_circle( [ $$mc[0],  $$mc[1]], $mr, 0-$Ba, -$Rb+$Ba); }
    if ($Rshape == 3) {
	silk_start( $$mc[0]          ,  $$mc[1] - $$rc[1] + $ir);
	silk_line ( $$mc[0] + $$rc[0],  $$mc[1] - $$rc[1] + $ir);
    }
    if ($ir) { silk_circle([  $$mc[0] + $$rc[0], $$mc[1] - $$rc[1]], $ir, 90+$Ra, $Rb); }

    # right line
    silk_start( $$in[0], +$$mc[1]-$$rc[1]);
    if ($yposts) {
	for my $ty (reverse @ylist) {
	    silk_line (  $$in[0], $ty + $$Yc[1] );
	    if ($ir) { silk_circle([ $$in[0] - $ir, $ty + $$Yc[1] ], $ir, 180, $Yb); }
	    if ($Yshape == 3) {
		silk_start( $$in[0]-$ir, $ty + $$Yc[1] - $ir);
		silk_line ( $yx        , $ty + $$Yc[1] - $ir);
	    }
	    if ($yr) { silk_circle([ $yx,  $ty], $yr, 90-$Ya, -2*$Yb); }
	    if ($Yshape == 3) {
		silk_start( $yx        , $ty - $$Yc[1] + $ir);
		silk_line ( $$in[0]-$ir, $ty - $$Yc[1] + $ir);
	    }
	    if ($ir) { silk_circle([  $$in[0] - $ir, $ty - $$Yc[1] ], $ir, 90+$Ya, $Yb); }
	    silk_start(  $$in[0], $ty - $$Yc[1] );
	}
    }
    silk_line ( $$in[0], -$$mc[1]+$$rc[1]);

    # right top
    if ($ir) { silk_circle([ $$mc[0] + $$rc[0], -$$mc[1] + $$rc[1]], $ir, 180, $Rb); }
    if ($Rshape == 3) {
	silk_start($$mc[0] + $$rc[0], -$$mc[1] + $$rc[1] - $ir);
	silk_line ($$mc[0]          , -$$mc[1] + $$rc[1] - $ir);
    }
    if ($mr) { silk_circle( [$$mc[0], -$$mc[1]], $mr, 90-$Ra, -$Rb+$Ba); }
    if ($Bshape == 3) {
	silk_start($$mc[0] - $mr, -$$mc[1]);
	silk_line ($$mc[0] - $mr, -$$in[1] + $ir);
    }
    if ($ir) { silk_circle([ $$mc[0] - $$bc[1], -$$in[1] + $ir], $ir, 180+$Ba, $Bb); }

    # top line
    silk_start( $$mc[0]-$$bc[1], -$$in[1]);
    if ($xposts) {
	for my $tx (reverse @xlist) {
	    silk_line( $tx + $$Xc[1], -$$in[1]);
	    if ($ir) { silk_circle([ $tx + $$Xc[1], -$$in[1] + $ir], $ir, 270, $Xb); }
	    if ($Xshape == 3) {
		silk_start($tx + $$Xc[1] - $ir, -$xy);
		silk_line ($tx + $$Xc[1] - $ir, -$$in[1]+$ir);
	    }
	    if ($xr) { silk_circle([ $tx, -$xy], $xr, 180-$Xa, -2*$Xb); }
	    if ($Xshape == 3) {
		silk_start($tx - $$Xc[1] + $ir, -$$in[1]+$ir);
		silk_line ($tx - $$Xc[1] + $ir, -$xy);
	    }
	    if ($ir) { silk_circle([ $tx - $$Xc[1], -$$in[1] + $ir], $ir, 180+$Xa, $Xb); }
	    silk_start( $tx - $$Xc[1], -$$in[1]);
	}
    }
    silk_line (-$$mc[0]+$$bc[1], -$$in[1]);
}

sub gen_box_inner_radi( @ ) {
    my $name = shift;
    my $doc = shift;

    my $ox = shift; # box outer dims.
    my $oy = shift;

    my $mx = shift; # box mounting holes
    my $my = shift;

    my $Px = shift; # inner major dims, the pcb has to be smaller than this
    my $Py = shift;

    my $CR = shift; # interiour corner radius, at box mounting holes
    my $cr = shift; # interiour corner radius, elsewhere

    my @arr = @_;

    element_start($name, $doc);

    # outer dims
    my $tmp = $silk_width;
    silk_width(0.18);
    pr("# outside dimensions\n");
    silk_start( $ox/2, $oy/2);
    silk_rline( -$ox,    0);
    silk_rline(    0, -$oy);
    silk_rline(  $ox,    0);
    silk_rline(    0,  $oy);

    # box mounting holes
    {
	my $l = 5;
	pr("# mounting holes\n");
	silk_cross( $mx/2, $my/2, $l);
	silk_cross(-$mx/2, $my/2, $l);
	silk_cross( $mx/2,-$my/2, $l);
	silk_cross(-$mx/2,-$my/2, $l);
    }

    silk_width();
    # enclusure internal outline
    {
	# at each corner there are thress arcs with center:
	my @c1 = ($mx/2 - $CR - $cr, $Py/2 - $cr);
	my @c2 = ($mx/2, $my/2);
	my @c3 = ($Px/2 - $cr, $my/2 - $CR - $cr);

	my $dx = ($Px - $mx)/2;
	my $dy = ($Py - $my)/2;
	my $px = $mx/2 - $CR;
	my $py = $my/2 - $CR;

	pr("# inside outline, pcb has to be smaller\n");
	# start at top left, top horizontal line going around clockwise
	silk_start( -$px, -$my/2);
	silk_line(  -$px, -$Py/2);
	silk_line(   $px, -$Py/2);
	silk_line(   $px, -$my/2);
	silk_arc( [ $mx/2, -$my/2], $CR,   0,  90);

	silk_start(  $mx/2, -$py);
	silk_line(   $Px/2, -$py);
	silk_line(   $Px/2,  $py);
	silk_line(   $mx/2,  $py);
	silk_arc( [ $mx/2,  $my/2], $CR, -90, 90);

	silk_start(  $px,  $my/2);
	silk_line(   $px,  $Py/2);
	silk_line(  -$px,  $Py/2);
	silk_line(  -$px,  $my/2);
	silk_arc( [-$mx/2,  $my/2], $CR, 180,  90);

	silk_start( -$mx/2,  $py);
	silk_line(  -$Px/2,  $py);
	silk_line(  -$Px/2, -$py);
	silk_line(  -$mx/2, -$py);
	silk_arc( [-$mx/2, -$my/2], $CR,  90, 90);

    }

    for my $r (@arr) {
	iterate_fdyxxx(@$r);
    }

    element_stop();
}

sub gen_fibox_tempo_all() {
    my $dia  = 7;
    my $iod  = [ 4.5, $dia ];
    my $iodn = [ 0.18, $dia ];
    my @arr  = (
	[
	    "fibox_tempo_TA191209T.fp",
"# http://www.fibox.se/documents/tuoteluettelo/2012/FIBOX_2012_Catalogues_swe_web.pdf
# http://www.fibox.com/documents/tuoteluettelo/2012/FIBOX_2012_Catalogues_eng_web.pdf
# http://www.fibox.se/catalog/335/product/2438/5814005_SWE1.html\n",
	    187, 122, # outside dim
	    163, 98,  # box mounting holes
	    175, 110, # inner major dim
	    11, 0, # int. radi
	    [
		\&gen_box_pcb_mounting_holes,
		[ $iod, 0, 130/2 ], # [ y, x1, x2, ... ]
		[ $iod, 65/2, 136/2 ],
		[ $iod, 80/2, 0 ],
		[ $iod, 91/2, 0 ],
	    ],
	    [
		\&gen_box_pcb_cstandoff,
		[ [ 0.18, $dia ], 95/2, 100/2 ],
	    ],
	    [
		\&gen_box_pcb_rstandoff,
		[ [ 0.18, 1.5, 13], 0, 130/2 ],
		[ [ 0.18, 13, 1.5], 91/2, 0 ],
	    ],
	    #[ 91/2, 0 ], [ 0, 130/2 ], # along-x studs, along-y studs
	],
	[
	    "fibox_tempo_TA191209T_4p.fp",
"# http://www.fibox.se/documents/tuoteluettelo/2012/FIBOX_2012_Catalogues_swe_web.pdf
# http://www.fibox.com/documents/tuoteluettelo/2012/FIBOX_2012_Catalogues_eng_web.pdf
# http://www.fibox.se/catalog/335/product/2438/5814005_SWE1.html\n",
	    187, 122, # outside dim
	    163, 98,  # box mounting holes
	    175, 110, # inner major dim
	    11, 0, # int. radi
	    [
		\&gen_box_pcb_mounting_holes,
		[ $iod, 65/2, 136/2 ],
	    ],
	    [
		\&gen_box_pcb_cstandoff,
		[ $iodn, 95/2, 100/2 ],
		[ $iodn, 0, 130/2 ], # [ y, x1, x2, ... ]
		[ $iodn, 80/2, 0 ],
		[ $iodn, 91/2, 0 ],
	    ],
	    [
		\&gen_box_pcb_rstandoff,
		[ [ 0.18, 1.5, 13], 0, 130/2 ],
		[ [ 0.18, 13, 1.5], 91/2, 0 ],
	    ],
	    #[ 91/2, 0 ], [ 0, 130/2 ], # along-x studs, along-y studs
	],
	[
	    "fibox_tempo_TA191209T_0p.fp",
"# http://www.fibox.se/documents/tuoteluettelo/2012/FIBOX_2012_Catalogues_swe_web.pdf
# http://www.fibox.com/documents/tuoteluettelo/2012/FIBOX_2012_Catalogues_eng_web.pdf
# http://www.fibox.se/catalog/335/product/2438/5814005_SWE1.html\n",
	    187, 122, # outside dim
	    163, 98,  # box mounting holes
	    175, 110, # inner major dim
	    11, 0, # int. radi
	],
	[
	    "fibox_tempo_201x163.fp",
	    "# http://www.fibox.se/documents/tuoteluettelo/2012/FIBOX_2012_Catalogues_swe_web.pdf
# http://www.fibox.com/documents/tuoteluettelo/2012/FIBOX_2012_Catalogues_eng_web.pdf
# http://www.fibox.se/catalog/335/product/2438/5814005_SWE1.html\n",
	    201, 163, # outside dim
	    181, 113,  # box mounting holes
	    190.9, 152.9, # inner major dim
	    13, 0, # int. radi
	    [
		\&gen_box_pcb_mounting_holes,
		[ $iod, 0, 168/2, 150/2 ], # [ y, x1, x2, ... ]
		[ $iod, 65/2, 130/2 ],
		[ $iod, 89/2, 149/2 ],
		[ $iod, 108/2, 136/2 ],
		[ $iod, 110/2, 0 ],
		[ $iod, 130/2, 0 ],
	    ],
	],
	[
	    "fibox_tempo_201x163_8p.fp",
	    "# http://www.fibox.se/documents/tuoteluettelo/2012/FIBOX_2012_Catalogues_swe_web.pdf
# http://www.fibox.com/documents/tuoteluettelo/2012/FIBOX_2012_Catalogues_eng_web.pdf
# http://www.fibox.se/catalog/335/product/2438/5814005_SWE1.html\n",
	    201, 163, # outside dim
	    181, 113,  # box mounting holes
	    190.9, 152.9, # inner major dim
	    13, 0, # int. radi
	    [
		\&gen_box_pcb_mounting_holes,
		[ $iod, 0, 168/2 ], # [ y, x1, x2, ... ]
		[ $iod, 108/2, 136/2 ],
		[ $iod, 130/2, 0 ],
	    ],
	],

	[
	    "hammond_1555V2GY.fp",
	    "# https://www.farnell.com/datasheets/1806560.pdf\n",
	    240, 160, # outside dim
	    227, 127,  # box mounting holes
	    234, 148.26, # inner major dim
	    6.5, 0, # int. radi
	    [
		\&gen_box_pcb_mounting_holes,
		[ $iod, 0, 216/2 ], # [ y, x1, x2, ... ]
		[ $iod, 75.01/2, 216/2 ],
		[ $iod, 138.50/2, 0, 201.50/2 ],
	    ],
	    [
		\&gen_box_pcb_rstandoff,
		[ [ 0.18, 1.5, 13], 0, 216/2 ],
	    ],
	],
    );

    for my $r (@arr) {
	gen_box_inner_radi( @$r );
    }
}
#gen_fibox_tempo_all();

sub gen_bernstein() {
    my $dia  = 8;
    my $iod  = [ 3.5, $dia ];
    my @arr  = (
	[
	    "bernstein_ct622.fp",
"# http://www.bernstein.eu/fileadmin/downloads/pdf/en/gehaeusetechnik/BERNSTEIN-complete-range-enclosure-systems.pdf p.51
",
	    160, 80, # outside dim
	    148.3, 50.2,  # box mounting holes
	    154, 74, # inner major dim
	    (148.3 - 137)/2, 0, # radi at mounting hole
	    [
		\&gen_box_pcb_mounting_holes,
		[ $iod, 0, 136/2 ], # [ y, x1, x2, ... ]
		[ $iod, 58/2, 0, 60/2, 121.5/2 ],
	    ],
	],
    );

    for my $r (@arr) {
	gen_box_inner_radi( @$r );
    }
}
#gen_bernstein();

sub gen_obo_t60($) {
    my $suffix = shift;
    my $xdoc = "";
    if ($suffix eq "_cut") {
	$xdoc = "# cut away a few things at the bottom of the enclosure with a bench mill\n";
    }
    $round_first_pin = 1;
    element_start("obo_t60$suffix.fp",
"# Obo T60 Kabelabzweigkasten
# http://www.obo.de/media/T-Serie_de.pdf p.18
# http://www.obo.de/dam/getFile/30/51ABTP7P3LN8U53CNCC91MT4-2007061-KSTP1.stp
$xdoc
");
    {
	pr "  ### exteriour\n";
	my $ol  = 112/2;
	my $ocs = 15; # outer corner segment length
	my $ox  = $ol - $ocs/$s2;
	silk_start(-$ox, $ol);
	silk_rline(2*$ox,0);
	silk_start($ol, -$ox);
	silk_rline(0,2*$ox);
	silk_start($ox, -$ol);
	silk_rline(-2*$ox,0);
	silk_start(-$ol, $ox);
	silk_rline(0,-2*$ox);

	# outside corners
	my $och =  1; # radius sticout from 45 deg bevel
	my $ocr = circle_segment_r($ocs, $och);
	my $oca = asin($ocs/(2*$ocr));
	$oca = int(rad_deg($oca)+0.5); # make it whole degrees
	$ocr = $ocs / (2*sin(deg_rad($oca))); # adj radius to rounded angle
	#print "$ocr $oca\n";
	my $ocos = cos(deg_rad(45-$oca));
	my $occ = $ol - $ocr + $ocr * (1 - $ocos); # center of corner radius
	#print "$ocos\n";
	silk_arc([-$occ, $occ], $ocr,     45-$oca, 2*$oca);
	silk_arc([ $occ, $occ], $ocr,  90+45-$oca, 2*$oca);
	silk_arc([ $occ,-$occ], $ocr, 180+45-$oca, 2*$oca);
	silk_arc([-$occ,-$occ], $ocr, 270+45-$oca, 2*$oca);
    }

    {
	pr "  ### interiour\n";
	my $il = 99/2;
	#my $is = 63/2;
	#my $ic = 87/2; # inner corner radius center
	#my $ir = $ic - $is; # ir = 18
	my $ir = 35/2;
	my $ic = int(10*(96 + 2*$ir) / sqrt(2))/10.0 / 2; # diagonal between centres -> side
	my $is = $ic - $ir;

	silk_start(-$is, -$ic);
	silk_line( -$is, -$il);
	silk_line(  $is, -$il);
	silk_line(  $is, -$ic);
	silk_arc( [-$ic, -$ic], $ir,  90, 90);
	silk_cross(-$ic, -$ic, 4);

	silk_start( $ic, -$is);
	silk_line(  $il, -$is);
	silk_line(  $il,  $is);
	silk_line(  $ic,  $is);
	silk_arc( [-$ic,  $ic], $ir, 180, 90);
	silk_cross(-$ic,  $ic, 4);

	silk_start( $is,  $ic);
	silk_line(  $is,  $il);
	silk_line( -$is,  $il);
	silk_line( -$is,  $ic);
	silk_arc( [ $ic,  $ic], $ir, 270, 90);
	silk_cross( $ic,  $ic, 4);

	silk_start(-$ic,  $is);
	silk_line( -$il,  $is);
	silk_line( -$il, -$is);
	silk_line( -$ic, -$is);
	silk_arc( [ $ic, -$ic], $ir,   0, 90);
	silk_cross( $ic, -$ic, 4);

	pr "  ### cable glands\n";
	my $gx = 32/2;
	#my $gd = 25; # gland hole diameter
	my $gh = $il - 4.5;
	my $gri = 22.5 / 2;
	my $gro = 27 / 2;

	silk_width(0.13);
	pr "  # top\n";
	silk_start(-$gro, -$il);
	silk_line( -$gri, -$gh);
	silk_line(  $gri, -$gh);
	silk_line(  $gro, -$il);
	pr "  # left\n";
	silk_start(-$il, -$gx-$gro);
	silk_line( -$gh, -$gx-$gri);
	silk_line( -$gh, -$gx+$gri);
	silk_line( -$il, -$gx+$gro);
	silk_start(-$il,  $gx-$gro);
	silk_line( -$gh,  $gx-$gri);
	silk_line( -$gh,  $gx+$gri);
	silk_line( -$il,  $gx+$gro);
	pr "  # bottom\n";
	silk_start(-$gx-$gro,  $il);
	silk_line( -$gx-$gri,  $gh);
	silk_line( -$gx+$gri,  $gh);
	silk_line( -$gx+$gro,  $il);
	silk_start( $gx-$gro,  $il);
	silk_line(  $gx-$gri,  $gh);
	silk_line(  $gx+$gri,  $gh);
	silk_line(  $gx+$gro,  $il);
	pr "  # right\n";
	silk_start( $il, -$gx-$gro);
	silk_line(  $gh, -$gx-$gri);
	silk_line(  $gh, -$gx+$gri);
	silk_line(  $il, -$gx+$gro);
	silk_start( $il,  $gx-$gro);
	silk_line(  $gh,  $gx-$gri);
	silk_line(  $gh,  $gx+$gri);
	silk_line(  $il,  $gx+$gro);
	silk_width();
    }
    if ($suffix eq "") {
	pr "  # center things\n";
	{
	    my $ri = 23/2;
	    my $ro = 26/2;
	    my $r = ($ro+$ri)/2;
	    my $w = ($ro-$ri)/2;
	    silk_width($w);
	    silk_circle([0,0], $r);
	    silk_width();
	}
	{
	    my $sep = 48/2;
	    my $w = 1;
	    my $rs = 14/2 + $w/2;
	    my $rl = 16.7/2 + $w/2;
	    my $dd = ($rl - $rs)/2;
	    #print "$rs $rl $dd\n";

	    silk_width($w);
	    silk_start(-$sep - $dd, -$rs);
	    silk_line( -$sep + $dd, -$rs);
	    silk_start(-$sep - $dd,  $rs);
	    silk_line( -$sep + $dd,  $rs);
	    silk_arc([-$sep-$dd,0], $rs, 270, 180);
	    silk_arc([-$sep+$dd,0], $rs,  90, 180);

	    silk_start( $sep - $rs, -$dd);
	    silk_line(  $sep - $rs,  $dd);
	    silk_start( $sep + $rs, -$dd);
	    silk_line(  $sep + $rs,  $dd);
	    silk_arc([$sep,-$dd], $rs, 180, 180);
	    silk_arc([$sep, $dd], $rs,   0, 180);

	    my $ss = 7;
	    my $od = 19;
	    my $hh = ($od - 15.5)/2;
	    my $rr = circle_segment_r($ss, $hh);
	    my $aa = asin($ss/(2*$rr));
	    $aa = int(rad_deg($aa)+0.5); # make it whole degrees
	    $rr = $ss / (2*sin(deg_rad($aa))); # adj radius to rounded angle
	    my $cc = $od/2 - $w/2 - $rr;
	    #print "$ss $hh $aa $rr $cc\n";
	    silk_arc([-$sep, -$cc], $rr,   270-$aa, 2*$aa);
	    silk_arc([-$sep,  $cc], $rr,    90-$aa, 2*$aa);
	    silk_arc([ $sep-$cc, 0], $rr,    0-$aa, 2*$aa);
	    silk_arc([ $sep+$cc, 0], $rr,  180-$aa, 2*$aa);
	    silk_width();
	}
    }
    {
	pr "  # mounting holes ST3.5x8.5\n";
	my $dr = 72/2;
	my $dd = $dr / $s2;
	my $ds = 92/2 / $s2;
	my $fl = 15/2;

	my $od = 7;
	my $fd = $od/2;
	my $id = 3.5 + 0.5; # screw + margin
	silk_width(0.8);

	pin($dr, 0, $id, $od);
	silk_start($dr, -$fl);
	silk_line( $dr, -$fd);
	silk_start($dr,  $fl);
	silk_line( $dr,  $fd);

	use_same_pin_no();
	pin(-$dr, 0, $id, $od);
	silk_start(-$dr, -$fl);
	silk_line( -$dr, -$fd);
	silk_start(-$dr,  $fl);
	silk_line( -$dr,  $fd);

	use_same_pin_no();
	pin(0, -$dr, $id, $od);
	silk_start(-$fl, -$dr);
	silk_line( -$fd, -$dr);
	silk_start( $fl, -$dr);
	silk_line(  $fd, -$dr);

	use_same_pin_no();
	pin(0,  $dr, $id, $od);
	silk_start(-$fl, $dr);
	silk_line( -$fd, $dr);
	silk_start( $fl, $dr);
	silk_line(  $fd, $dr);

	my $al = $fl / $s2;
	my $ad = $fd / $s2;

	if ($suffix eq "") {
	    use_same_pin_no();
	    pin(-$dd, -$dd, $id, $od);
	    silk_start(-$dd-$al, -$dd+$al);
	    silk_line( -$dd-$ad, -$dd+$ad);
	    silk_start(-$dd+$al, -$dd-$al);
	    silk_line( -$dd+$ad, -$dd-$ad);

	    use_same_pin_no();
	    pin( $dd,  $dd, $id, $od);
	    silk_start( $dd-$al,  $dd+$al);
	    silk_line(  $dd-$ad,  $dd+$ad);
	    silk_start( $dd+$al,  $dd-$al);
	    silk_line(  $dd+$ad,  $dd-$ad);
	}

	silk_width();

	silk_circle([-$ds,-$ds], 7/2);
	silk_circle([ $ds,-$ds], 7/2);
	silk_circle([ $ds, $ds], 7/2);
	silk_circle([-$ds, $ds], 7/2);

    }
    element_stop();
    $round_first_pin = 0;
}
#gen_obo_t60("");
#gen_obo_t60("_cut");

sub gen_electromatic_SC180_box() {
    my $doc = "
# box with 11-pin \"octal\" style connector at base
# The 11 pin octal connector seems to be derived from the 8 pin octal tube socket
# There is no doc, just measurements taken from a
# electromatc / S-system / SC 180 724 / supply 24VDC / recycler / 3-60sec
# plastic cover measures 34 * 80 * 72mm
";
    my $file = "electromatic_SC180_box.fp";

    my $xx = 76/2;
    my $yy = 60/2;
    element_start($file, $doc);
    silk_width(0.12);
    silk_start(-$xx, $yy);
    silk_rline(0, -2*$yy);
    silk_rline(2*$xx, 0);
    silk_rline(0, 2*$yy);

    # right and left notches
    silk_rline(-2, 2.2);
    silk_rline( 1, 0.8);
    silk_rline(-1, 5.5);

    silk_start(-$xx, $yy);
    silk_rline( 2, 2.2);
    silk_rline(-1, 0.8);
    silk_rline( 1, 5.5);

    # bottom
    silk_rline(6,0);
    silk_rline(0,-3);
    silk_arc( [$silk_x+3, $silk_y], 3, 0, -90);
    silk_start($silk_x+3, $silk_y-3);
    silk_rline(31, 0);
    silk_rline(4, 4);
    silk_rline(9, 0);
    silk_arc( [$silk_x  , $silk_y+1], 1, 270, -90);
    silk_start($silk_x+1, $silk_y+1);
    silk_rline(0, 1);
    silk_rline(18,0);

    #          1      2      3     4    5    6    7   8   9  10    11
    my @x = ( 12  , 20.75,  4.5,  4.5, 31, 40.5, 11, 21, 41, 40.5, 58);
    my @y = ( 53.5, 58.25, 58.5, 48.5, 11, 38.5, 11, 11, 11, 53.5, 28);
    # colour = "brun/svart röd brandgul gul grön blå vit grå vit svart brun
    for (my $ix = 0; $ix < @x; $ix++) {
	pin( - $xx + $x[$ix], -$yy + $y[$ix], 0.7, 1.5, "");
    }

    element_stop();
}
#gen_electromatic_SC180_box();

########################################
## SMT footprints ######################
########################################

sub pad_gen($$$$) {
    my $prefix = shift;
    my $doc_prefix = shift;
    my $r = shift;
    my $paste_as_outline = shift;

    my @names = @{$$r[0]};
    my @silk  = @{$$r[1]};
    my @pads  = @{$$r[2]};
    my @paste = @{$$r[3]};

    my $file = "${prefix}\L$names[0].fp";
    $file =~ tr/-/_/;
    my $ns = join(" ", @names);
    element_start("$file", "# $ns\n# $doc_prefix/$names[0].pdf\n");

    for my $ref (@pads) {
	my ($nn, $x, $y, $w, $h, $name, $popt, $r, $mask) = @$ref;
	if (defined($mask)) {
	    $mask_gap  = $mask;
	} else {
	    $mask_gap = $mask_gap_default;
	}
	#print "$x, $y, $w, $h / $name, $popt, $r, $nn\n";
	pad($x, $y, $w, $h, $name, $popt, $r, $nn);
    }
    if (@silk == 0) {
	silk_bb(0.32);
    } else {
	my $nn = 0;
	my $SW = 0;
	for my $rs (@silk) {
	    my @point = @$rs;
	    my $type = shift @point;
	    my $sw = shift @point;
	    my $x = shift @point;
	    my $y = shift @point;
	    if ($paste_as_outline) { $sw /= 10; }
	    silk_width($sw);
	    if ($SW < $sw) { $SW = $sw; }
	    my @bbw = bb_sort(@bounding_box);
	    @bbw = bb_enlarge($silk_w/2,@bbw);
	    silk_start($x, $y);
	    if ($type eq "lr") {
		while (@point) {
		    $x = shift @point;
		    $y = shift @point;
		    $nn += silk_rline($x, $y, \@bbw);
		}
	    } else {
	    }
	}
	if ($nn < 1) {
	    if (!$SW) { $SW = 0.25; }
	    print "$file: $SW\n";
	    silk_bb($SW);
	    silk_width();
	}
    }
    if ($paste_as_outline) {
	$pad_as_outline = 1;
	silk_width(0.005);
	for my $ref (@paste) {
	    my ($nn, $x, $y, $w, $h, $name, $popt, $r, $mask) = @$ref;
	    if (defined($mask)) {
		$mask_gap  = $mask;
	    } else {
		$mask_gap = $mask_gap_default;
	    }
	    pad($x, $y, $w, $h, $name, $popt, $r, $nn);
	}
	$pad_as_outline = 0;
	silk_width();
    }
    element_stop();

    for (my $ix = 1; $ix < @names; $ix++) {
	my $link = "${prefix}\L$names[$ix].fp";
	$link =~ tr/-/_/;
	`ln -sf $file $link`;
    }

    if (@paste) {
	$file = "${prefix}\L$names[0].sfp";
	$file =~ tr/-/_/;
	element_start("$file", "# solder paste rendered as pads\n# $ns\n# $doc_prefix/$names[0].pdf\n");
	for my $ref (@paste) {
	    my ($nn, $x, $y, $w, $h, $name, $popt, $r, $mask) = @$ref;
	    if (defined($mask)) {
		$mask_gap  = $mask;
	    } else {
		$mask_gap = $mask_gap_default;
	    }
	    pad($x, $y, $w, $h, $name, $popt, $r, $nn);
	}
	if (@silk == 0) {
	    silk_bb(0.32);
	} else {
	    for my $rs (@silk) {
		my @point = @$rs;
		my $type = shift @point;
		my $sw = shift @point;
		my $x = shift @point;
		my $y = shift @point;
		silk_width($sw);
		silk_start($x, $y);
		if ($type eq "lr") {
		    while (@point) {
			$x = shift @point;
			$y = shift @point;
			silk_rline($x, $y);
		    }
		} else {
		}
		silk_width();
	    }
	}
	element_stop();

	for (my $ix = 1; $ix < @names; $ix++) {
	    my $link = "${prefix}\L$names[$ix].sfp";
	    $link =~ tr/-/_/;
	    `ln -sf $file $link`;
	}
    }
    $mask_gap  = $mask_gap_default;
}


sub gen_ipc_782() {
    my $chip_resistor_dim =
"Figure 2 provides the component dimensions for chip resistors.
mm   [in]   L         T         W         S         H
comp.id     min  max  min  max  min  max  min  max  max
1005 [0402] 1.00 1.10 0.40 0.70 0.48 0.60 0.10 0.30 0.40
1608 [0603] 1.50 1.70 0.70 1.11 0.70 0.95 0.15 0.40 0.60
2012 [0805] 1.85 2.15 0.55 1.32 1.10 1.40 0.15 0.65 0.65
3216 [1206] 3.05 3.35 1.55 2.32 1.45 1.75 0.25 0.75 0.71
3225 [1210] 3.05 3.35 1.55 2.32 2.34 2.64 0.25 0.75 0.71
5025 [2010] 4.85 5.15 3.15 3.92 2.35 2.65 0.35 0.85 0.71
6332 [2512] 6.15 6.45 4.45 5.22 3.05 3.35 0.35 0.85 0.71
";
    my $chip_res_land_dim =
"    Comp_Id                    Y    C
RLP  mm   [in.]  Z    G    X    ref  ref  Placement_Grid
100A 1005 [0402] 2.20 0.40 0.70 0.90 1.30 2x6
101A 1608 [0603] 2.80 0.60 1.00 1.10 1.70 4x6
102A 2012 [0805] 3.20 0.60 1.50 1.30 1.90 4x8
103A 3216 [1206] 4.40 1.20 1.80 1.60 2.80 4x10
104A 3225 [1210] 4.40 1.20 2.70 1.60 2.80 6x10
105A 5025 [2010] 6.20 2.60 2.70 1.80 4.40 6x14
106A 6332 [2512] 7.40 3.80 3.20 1.80 5.60 8x16
";
    my $chip_cap_land_dim =
"                                                  Y    C
        Component Identifier                                   Placement Grid
RLP No.     (mm) [in]        Z (mm) G (mm) X (mm)  ref  ref (No. of Grid elements)
130A      1005 [0402]        2.20   0.40   0.70  0.90 1.30          2x6
131A      1310 [0504]        2.40   0.40   1.30  1.00 1.40          4x6
132A      1608 [0603]        2.80   0.60   1.00  1.10 1.70          4x6
133A      2012 [0805]        3.20   0.60   1.50  1.30 1.90          4x8
134A      3216 [1206]        4.40   1.20   1.80  1.60 2.80          4x10
135A      3225 [1210]        4.40   1.20   2.70  1.60 2.80          6x10
136A      4532 [1812]        5.80   2.00   3.40  1.90 3.90          8x12
137A      4564 [1825]        5.80   2.00   6.80  1.90 3.90         14x12
";
    my $doc = "# p71... https://www.pcb-3d.com/wordpress/wp-content/uploads/ipc-sm-782a_amendment_1_and_2.pdf\n";
    my $str =
	$chip_res_land_dim .
	$chip_cap_land_dim .
	"";
    my $sw = 0.2;
    my $sc = 0.05;

    for my $line (grep { m/^\d/ } split(/\n/, $str)) {
	my ($rlp, $sz, $szi, $Z, $G, $X, $Y, $C, $pg) = split(/\s+/, $line);
	my $xc = ($G + $Z)/4;
	my $cr = ipc_corner($Y);
	my $wx = substr($sz, 0, 2)/10;
	my $wy = substr($sz, 2, 2)/10;
	my $xi = $G/2 - $mask_gap - $sw/2;
	my $yi = $wy/2;

	for my $opt (("r", "")) {
	    if ($opt eq "") { $cr = 0; }
	    my $file = sprintf "ipc782_%s_%s%s.fp", $rlp, $sz, $opt;
	    element_start($file, $doc);
	    pad( -$xc, 0, $Y, $X, undef, "", $cr);
	    pad(  $xc, 0, $Y, $X, undef, "", $cr);

	    if ($xi > 0) {
		silk_width($sw);
		silk_start(-$xi, -$yi);
		silk_line ( $xi, -$yi);
		silk_start(-$xi,  $yi);
		silk_line ( $xi,  $yi);
	    }
	    silk_bb($sc);
	    element_stop();
	}
    }


}
#gen_ipc_782();

sub gen_ipc_7315b() {
    my $str =
" EIA  Metric         Density Level A:               Density Level B:               Density Level C:
Size   Size         Maximum (Most)                 Median (Nominal)               Minimum (Least)
Code  Code        Land Protrusion (mm)           Land Protrusion (mm)           Land Protrusion (mm)
              C      Y      X      V1   V2   C      Y      X      V1   V2   C      Y      X      V1   V2
0402   1005  0.50   0.72   0.72   2.20 1.20 0.45   0.62   0.62   1.90 1.00 0.40   0.52   0.52   1.60 0.80
0603   1608  0.90   1.15   1.10   4.00 2.10 0.80   0.95   1.00   3.10 1.50 0.60   0.75   0.90   2.40 1.20
0805   2012  1.00   1.35   1.55   4.40 2.60 0.90   1.15   1.45   3.50 2.00 0.75   0.95   1.35   2.80 1.70
1206   3216  1.60   1.35   1.90   5.60 2.90 1.50   1.15   1.80   4.70 2.30 1.40   0.95   1.70   4.00 2.00
1210   3225  1.60   1.35   2.80   5.65 3.80 1.50   1.15   2.70   4.70 3.20 1.40   0.95   2.60   4.00 2.90
1210L  3225L 1.50   1.60   2.90   5.60 3.90 1.40   1.40   2.80   4.70 3.30 1.30   1.20   2.70   4.00 3.00
1808   4520  2.30   1.75   2.30   7.40 3.30 2.20   1.55   2.20   6.50 2.70 2.10   1.35   2.10   5.80 2.40
1812   4532  2.15   1.60   3.60   6.90 4.60 2.05   1.40   3.50   6.00 4.00 1.95   1.20   3.40   5.30 3.70
1825   4564  2.15   1.60   6.90   6.90 7.90 2.05   1.40   6.80   6.00 7.30 1.95   1.20   6.70   5.30 7.00
2220   5650  2.75   1.70   5.50   8.20 6.50 2.65   1.50   5.40   7.30 5.90 2.55   1.30   5.30   6.60 5.60
2225   5664  2.70   1.70   6.90   8.10 7.90 2.60   1.50   6.80   7.20 7.30 2.50   1.30   6.70   6.50 7.00
"; # the 3225L is for cap. >= 22uF
    my $doc = "# p.12 https://www.elfa.se/Web/Downloads/_t/ds/KEM_C1002_X7R_SMD_eng_tds.pdf\n";
    my %dim;
    my @ltr = qw/ A B C /;
    my $sw = 0.2;
    silk_width($sw);

    for my $line (grep { m/^\d/ } split(/\n/, $str)) {
	my ($eia, $sz, @fld) = split(/\s+/, $line);
	$dim{$sz} = [ [ @fld[0..4] ], [ @fld[5..9] ], [ @fld[10..14] ] ];
    }
    #print Dumper(\%dim);
    for my $sz (sort keys %dim) {
	#print "$sz\n";
	my @arr = @{$dim{$sz}};
	for (my $ix = 0; $ix < @arr; $ix++) {
	    my $wx = substr($sz, 0, 2)/10;
	    my $wy = substr($sz, 2, 2)/10;
	    my @dim = @{$dim{$sz}[$ix]};
	    my $cr = ipc_corner($dim[1]);

	    for my $opt (("r", "")) {
		my $file = sprintf "ipc7351b_%s%s%s.fp", $sz, $ltr[$ix], $opt;
		element_start($file, $doc);
		pad( -$dim[0], 0, $dim[1], $dim[2], undef, "", $cr);
		pad(  $dim[0], 0, $dim[1], $dim[2], undef, "", $cr);
		pkg_body_rect([$wx,$wy],0);
		element_stop();
		$cr = 0;
	    }
	}
    }
    silk_width();
}
#gen_ipc_7315b();

sub pkg_rect_pads($$$;$$) {
    # make pads on four sides
    my $N = shift;
    my $pc = shift; # [ pad centerline x-wise, y-wise ]
    my $pin = shift; # [ pitch, width, length, cr ]
    my $pnum = shift;
    my $pname = shift;

    my ($pad_x, $pad_y) = @$pc;
    my ($pitch, $pad_wid, $pad_len, $cr) = @$pin;

    my @name = ();
    if (defined($pname)) {
	@name = @$pname;
    }

    my @N; # final pin pos on left, bottom, right, top side
    if (@$N == 2) {
	my ($nx, $ny) = @$N;
	@N = ($ny, $ny+$nx, $ny+$nx+$ny, $ny+$nx+$ny+$nx);
    } elsif (@$N == 4) {
	@N = ($$N[0], $$N[0]+$$N[1], $$N[0]+$$N[1]+$$N[2], $$N[0]+$$N[1]+$$N[2]+$$N[3] );
    }
    my @num;
    if (defined($pnum)) {
	@num = @$pnum;
    } else {
	@num = (1..$N[3]);
    }

    #print " N:   [ ", join(" ", @$N), " ]\n";
    #print " pc:  [ $$pc[0] $$pc[1] ]\n";
    #print " pin: [ $$pin[0] $$pin[1] $$pin[2] $$pin[3] ]\n";
    #print " num: ( ", join(" ", @num), " )\n";
    #print " name ( ", join(" ", @$pname), " )\n" if (defined($pname));
    #print "\n";

    my $ix = 0;
    my $mid;

    $mid = ($N[0]-1 - 0)/2;
    for ( ; $ix < $N[0]; $ix++) {
	# left side
	if (defined($num[$ix])) {
	    pad( -$pad_x, ($ix - $mid)*$pitch, $pad_len, $pad_wid, $name[$ix], "", $cr, $num[$ix]);
	}
    }

    $mid = ($N[1]-1 - $N[0])/2 + $N[0];
    for ( ; $ix < $N[1]; $ix++) {
	# bottom side
	if (defined($num[$ix])) {
	    pad(  ($ix - $mid)*$pitch, $pad_y, $pad_wid, $pad_len, $name[$ix], "", $cr, $num[$ix]);
	}
    }

    $mid = ($N[2]-1 - $N[1])/2 + $N[1];
    for ( ; $ix < $N[2]; $ix++) {
	# right side
	if (defined($num[$ix])) {
	    pad(  $pad_x,  ($mid - $ix)*$pitch, $pad_len, $pad_wid, $name[$ix], "", $cr, $num[$ix]);
	}
    }

    $mid = ($N[3]-1 - $N[2])/2 + $N[2];
    for ( ; $ix < $N[3]; $ix++) {
	# top side
	if (defined($num[$ix])) {
	    pad( ($mid - $ix)*$pitch, -$pad_y, $pad_wid, $pad_len, $name[$ix], "", $cr, $num[$ix]);
	}
    }
}

sub pkg_thermal_pad($$;$$) {
    # make a center thermal pad, possible with a bunch of vias
    my $px = shift;
    my $py = shift;
    my $via_pitch  = shift;
    my $hole = shift;

    my $str = "";
    if (!defined($px) || !defined($py) || $px == 0 || $py == 0) { return $str; }

    pr(" # Thermal pad\n");
    pad(  0, 0, $px, $py, undef, "", 0, 0);

    if (!defined($via_pitch)) { $via_pitch = 0; }
    if (!defined($hole)) { $hole = 0.4; }

    if ($via_pitch > 0 && $hole > 0) {
	my $d_cu = $hole + 0.2;
	# max # of vias in thermal pad:
	my $cx = $via_pitch * int( ($px - $d_cu) / $via_pitch ) + 1;
	my $cy = $via_pitch * int( ($py - $d_cu) / $via_pitch ) + 1;

	my $end_x = ($cx - 1)/2;;
	my $sta_x = - $end_x;
	my $end_y = ($cy - 1)/2;;
	my $sta_y = - $end_y;

	#print "$px $py $via_pitch / $cx $cy / $end_x $end_y\n";

	if (!$pr_h) { pr_inc(); }
	$pr_save = "";

	for (my $vx = $sta_x; $vx <= $end_x; $vx += $via_pitch) {
	    for (my $vy = $sta_y; $vy <= $end_y; $vy += $via_pitch) {
		pin($vx, $vy, $hole, $d_cu, "thermal", undef, 0);
	    }
	}
	if (!$pr_h) { pr_dec(); }
	$str = $pr_save;
    }

    return $str;
}
sub pkg_body_rect($;$) {
    # draw a rectangular body outline
    my $body = shift;
    my $flag = shift // 0;

    my $radi = 0;
    my $sw = 0;
    if (defined($$body[3])) { $sw   = $$body[3]; }
    if (defined($$body[2])) { $radi = $$body[2]; }
    my $nn = 0;
    my $Body = [ $$body[0], $$body[1] ];

    pr("# Body\n");
    if ($sw) { silk_width($sw); }
    my @bbw = bb_sort(@bounding_box);
    @bbw = bb_enlarge($silk_w/2,@bbw);
    $nn = silk_crect($origin, $Body, $radi, \@bbw);
    if ($flag && $nn < 1) {
	my $min = [ $bbx1 - $silk_w/2, $bby1 - $silk_w/2];
	my $max = [ $bbx2 + $silk_w/2, $bby2 + $silk_w/2];
	$nn = silk_rect($min, $max);
    }
    if ($sw) { silk_width(); }
    $nn;
}
sub pkg_body_lcd($;@) {
    my $data = shift;
    my ($sz_x, $sz_y, $bump_width, $bump_height) = @$data;

    my @bbw = bb_sort(@bounding_box);
    @bbw = bb_enlarge($silk_w/2,@bbw);
    silk_crect($origin, [$sz_x, $sz_y], 0, \@bbw);

    # cheap LCD's have bump of glass fused to the side between the 1st and last pin
    silk_start(-$bump_width/2,      -$sz_y/2);
    silk_rline(             0, -$bump_height);
    silk_rline(   $bump_width,             0);
    silk_rline(             0,  $bump_height);
}

sub pkg_twoPad($$$@) {
    # make two pads with body outline, pad 1 is above, 2 is below
    my $pfx = shift;
    my $doc = shift;
    my $refdes = shift;
    my @data = @_;

    my %ext = ("_A" => 0, "_B" => 0.5, "_C" => 1);
    for my $data (@data) {
	for my $key (keys %ext) {
	    my ( $body, $cy, $px, $py, $type, $Doc) = @$data;
	    my $cx = 0;
	    my $val = $ext{$key};
	    my $file = $pfx . $type . $key . ".fp";
	    $py += $val;
	    $cy += $val/2;
	    if (defined($Doc)) { $doc = $Doc; }

	    element_start($file, $doc, $type, $refdes);
	    pad(  $cx, -$cy, $px, $py);
	    pad(  $cx,  $cy, $px, $py);
	    pkg_body_rect($body);
	    element_stop();
	}
    }
}

sub swapR($) {
    my $r = shift;
    my @a = @$r;
    my $t = $a[0];
    $a[0] = $a[1];
    $a[1] = $t;
    [ @a ];
}
sub pkg_smdnRm($$$$$;$$$) {
    my $name = shift;
    my $doc  = shift;
    my $N = shift;
    my $pin  = shift;
    my $body = shift;

    #  optional
    my $thermal = shift;
    my $pnum = shift;
    my $pname = shift;

    $N =  swapR($N);
    $body = swapR($body);
    if (defined($thermal)) {
	$thermal = swapR($thermal);
    }
    pkg_smdnm($name, $doc, $N, $pin, $body, $thermal, $pnum, $pname);
}
sub pkg_smdnm($$$$$;$$$) {
    my $name = shift;
    my $doc  = shift;
    my $N = shift;
    my $pin  = shift;
    my $body = shift;

    #  optional
    my $thermal = shift;
    my $pnum = shift;
    my $pname = shift;

    my ( $e, $b, $L ) = @$pin;
    my ( $D2,$E2 )    = @$thermal;

    my %ol = ( b => 0, c => 0.4, d => 0.6 ); # , x => 1.5  a => -0.2,
    for my $key (sort keys %ol) {
	my $outer_len = $ol{$key};
	my $pfx;

	$pfx = "${name}_${key}s";
	pkg_smdn($pfx, $doc, $N, [ $e, $b, $L, $outer_len, 0 ], $body, [$D2,$E2], $pnum, $pname);
	$pfx = "${name}_${key}s3";
	pkg_smdn($pfx, $doc, $N, [ $e, $b, $L, $outer_len, 0 ], $body, [$D2,$E2,1.00,0.30], $pnum, $pname);
	$pfx = "${name}_${key}s4";
	pkg_smdn($pfx, $doc, $N, [ $e, $b, $L, $outer_len, 0 ], $body, [$D2,$E2,1.00,0.40], $pnum, $pname);

	if ($outer_len >= $b/2) {
	    # theese are woth round pad ends
	    $pfx = "${name}_${key}r";
	    pkg_smdn($pfx, $doc, $N, [ $e, $b, $L, $outer_len, 1 ], $body, [$D2,$E2], $pnum, $pname);
	    $pfx = "${name}_${key}r3";
	    pkg_smdn($pfx, $doc, $N, [ $e, $b, $L, $outer_len, 1 ], $body, [$D2,$E2,1.00,0.30], $pnum, $pname);
	    $pfx = "${name}_${key}r4";
	    pkg_smdn($pfx, $doc, $N, [ $e, $b, $L, $outer_len, 1 ], $body, [$D2,$E2,1.00,0.40], $pnum, $pname);
	}
    }
}
sub pkg_smdnR($$$$$;$$$) {
    # Note, if you use $pnum, check the result
    my $name = shift;
    my $doc  = shift;
    my $N = shift;
    my $pin  = shift;
    my $body = shift;

    #  optional
    my $thermal = shift;
    my $pnum = shift;
    my $pname = shift;

    $N =  swapR($N);
    $body = swapR($body);
    if (defined($thermal)) {
	$thermal = swapR($thermal);
    }

    pkg_smdn($name, $doc, $N, $pin, $body, $thermal, $pnum, $pname);
}
sub pkg_smdn($$$$$$;$$$) {
    # variations:  pad length L1 inside/outside of body, square or rounded pads
    ## TODO terminal size to pad size, thermal vias
    ##    detect corner terminals nearly colliding

    # packages with leadless terminals like son/qfn/dfn
    # Note, pin #1 is top left if $N[1] > 0, else bottom left

    # doc: https:/www.nxp.com/docs/en/application-note/AN1902.pdf
    # the terminal ends can be: int +0.05
    #  3.4.1 Fully-exposed terminal ends: >= 0.2 ext.
    #  3.4.2 Pull-back terminal ends: no ext.
    #  3.4.3 Terminal ends with side wettable flank: >= 0.40, 0.60
    # p12/51: side same size
    # p13.51: mask_gap = 0.060 to 0.075, solder mask >= 0.075
    # o16/51: distance between terminal and thermal pad >= 0.25

    # some documentation
    #   www.jedec.org JEP95 MO-220K01.pdf
    #   www.jedec.org JEP95 MO-229F.pdf
    #   https://www.nxp.com/docs/en/application-note/AN1902.pdf
    #   https://www.ftdichip.com/Support/Documents/TechnicalNotes/TN_166 FTDI Example IC PCB Footprints.pdf
    #   https://www.custommmic.com/resources/custom-mmic-app-note-105.pdf
    #   http://www.farnell.com/datasheets/2853109.pdf
    #   ti.com scba017d.pdf
    #   ti.com sloa122.pdf
    #   cypress.com 001-72845_AN72845_Design_Guidelines_For_Cypress_Quad_Flat_No_Lead_QFN_Packaged_Devices.pdf
    # Unfortenately I don't have theese:
    #   IPC-7525 Stencil Design Guidelines
    #   IPC-7351: Generic Requirements for Surface Mount Design and Land Pattern Standard
    #   IPC-7093: Design and Assembly Process Implementation for Bottom Termination Components


    my $name = shift;
    my $doc  = shift;
    my $N = shift; # [ #pins positions on top/bottom sise (x), dito left/right (y) ]
    my $pin  = shift; # [ pitch, pin width, inner length, oouter length, corner_radius ]
    # body: [ x sz, y sz, index ] || &drawing_function || string, jedec D/D1, E/E1, h
    my $body = shift;

    #  optional
    # thermal: [ thermal pad x sz, y sz, via pitch, drill sz ]
    #  for the via pitch I have seen recommondateion from 0.8 to 1.3mm
    my $thermal = shift;
    my $pnum = shift;  # pin number at a pin position
    my $pname = shift; # pin pos. name

    my ($pitch, $terminal_width, $inner_len, $outer_len, $cr) = @$pin;
    if (!defined($outer_len)) { $outer_len = 0; }
    if (!defined($cr)) { $cr = 0; }
    if (!defined($thermal)) { $thermal = [ 0, 0 ]; }
    my @name = ();
    if (defined($pname)) {
	@name = @$pname;
    }

    my $inner_ext = 0.05; # pad needs to this much longer inwards than the component land
    my $terminal_width_ext = 0.05;
    my $wanted_mask_gap = 0.07;
    $inner_len += $inner_ext;

    my $err_flag = 0;
    # check gap between thermal pad and the other pads
    if ($$thermal[0] > 0 && $$thermal[1] > 0) {
	if ($$N[0]) {
	    # pads along the top and bottom side
	    my $gap = ($$body[1] - $$thermal[1])/2 - $inner_len;
	    if ($gap < $minimum{thermal_to_pad_distance}) {
		print "Bad component, gap (y, $gap) between pad and thermal pad to small\n";
		$err_flag = 1;
	    }
	}
	if ($$N[1]) {
	    # pads along the left/rigth side
	    my $gap = ($$body[0] - $$thermal[0])/2 - $inner_len;
	    if ($gap < $minimum{thermal_to_pad_distance}) {
		print "Bad component, gap (x, $gap) between pad and thermal pad to small\n";
		$err_flag = 1;
	    }
	}
    }

    # check that solder mask between pads is sufficiently wide
    {
	my $gap = $pitch - $terminal_width;
	my $mask_space = $minimum{solder_mask_width} + 2*$wanted_mask_gap;
	if ($gap < $mask_space - 2*$terminal_width_ext) {
	    $terminal_width -= $terminal_width_ext;
	    if ($pitch <= 0.5 && $gap < $mask_space + 2*$terminal_width_ext) {
		# ok
	    } else {
		print "Too small space between pads for solder mask\n";
		#$err_flag = 1;
	    }
	} else {
	    $terminal_width += $terminal_width_ext;
	}
	### TODO: check that mask isn't too thin
    }

    my $pad_len = $inner_len + $outer_len;
    my $pad_wid = $terminal_width;
    my $pad_c   = ($inner_len - $outer_len)/2;
    my $pad_x  = $$body[0]/2 - $pad_c;
    my $pad_y  = $$body[1]/2 - $pad_c;
    if ($cr) { $cr = $pad_wid/2; }
    my $file = $name . ".fp";

    if ($err_flag) {
	print "$name\n$doc";
	print " N:     [ $$N[0] $$N[1] ]\n";
	print " pin:   [ $$pin[0] $$pin[1] $$pin[2] $$pin[3] ]\n";
	print " body:  [ $$body[0] $$body[1] ]\n";
	print " therm: [ $$thermal[0] $$thermal[1] ]\n";
	print " pnum:  ( ", join(" ", @$pnum), " )\n";
	print " pname: ( ", join(" ", @name), " )\n";
	print "\n";
    }
    ######

    $mask_gap = $wanted_mask_gap;
    element_start($file, $doc);

    pkg_rect_pads($N, [$pad_x, $pad_y], [ $pitch, $pad_wid, $pad_len, $cr ], $pnum, $pname);

    my @bb_first = @{$bounding_box[0]};
    my @bb_last  = @{$bounding_box[$#bounding_box]};
    # look at the cu part only
    @bb_first = ($bb_first[0]+$mask_gap, $bb_first[1]-$mask_gap, $bb_first[2]+$mask_gap, $bb_first[3]-$mask_gap);
    @bb_last  = ($bb_last [0]+$mask_gap, $bb_last [1]-$mask_gap, $bb_last [2]+$mask_gap, $bb_last [3]-$mask_gap);

    # check corner terminal collisions
    # assuming that pad in 1st and last posision isn't skipped
#    {
#	my $d;
#	if ($bb_first[1] <= $bb_last[0]) { # top row start right of left row
#	    if ($bb_first[2] <= $bb_last[3]) { # left row goew above bottom of top row
#	} elsif ($bb_first[0] <= $bb_last[1] && $bb_last[0] <= $bb_first[1]) {
#	    $d = $bb_first[2] - $bb_last[
#	}
#    }
    pkg_thermal_pad($$thermal[0], $$thermal[1], $$thermal[2], $$thermal[3]);

    silk_width(0.18);
    pkg_body_rect($body);

    pr(" # Index marker\n");
    my $body_min = $$body[0];
    if ($body_min > $$body[1]) { $body_min = $$body[1]; }
    my $rr = $body_min/25;
    my @bf = bb_enlarge($silk_w/2 + $mask_gap + $rr, \@bb_first);
    my @bl = bb_enlarge($silk_w/2 + $mask_gap + $rr, \@bb_last);
    # 0.2, so there is a little space between the corner and the index
    my $index_x = - $$body[0]/2 - $rr - 0.2;
    my $index_y = - $$body[1]/2 - $rr - 0.2;

    if ($index_x > $bl[0][0]) {
	$index_x = $bl[0][0];
    }
    if ($index_y > $bf[0][2]) {
	$index_y = $bf[0][2];
    }
    silk_circle([$index_x, $index_y], $rr);

    element_stop();
    silk_width();
    $mask_gap = $mask_gap_default;
}

sub pkg_smdpinsR($$$$$$;$$$) {
    my $name = shift;
    my $doc  = shift;
    my $N = shift;
    my $pin  = shift;
    my $body = shift;
    my $extent = shift;

    #  optional
    my $thermal = shift;
    my $pnum = shift;
    my $pname = shift;

    my $t;
    $t = $$N[0];
    $$N[0] = $$N[1];
    $$N[1] = $t;

    $t = $$body[0];
    $$body[0] = $$body[1];
    $$body[1] = $t;

    $t = $$extent[0];
    $$extent[0] = $$extent[1];
    $$extent[1] = $t;

    if (defined($thermal)) {
	$t = $$thermal[0];
	$$thermal[0] = $$thermal[1];
	$$thermal[1] = $t;
    }

    pkg_smdpins($name, $doc, $N, $pin, $body, $extent, $thermal, $pnum, $pname);
}
sub pkg_smdpins($$$$$$;$$$) {
    # smd packages with pins around the sides, like qfp, soic

    my $name = shift; # we add A, B, or C (ipc level) and r for rounded pads
    my $doc  = shift;
    my $N = shift; # [ #pins positions on top/bottom sise (x), dito left/right (y) ]a
    my $pin  = shift; # [ pitch, pin width, length, ix... ], jedec: [ e, b, L ]
    #  ix... = which entries in $ipc{x} to use (0 .. 3), defaults to 1..3
    # body: [ x sz, y sz, index ] || &drawing_function || string, jedec D/D1, E/E1, h
    my $body = shift; #  [ body_x, body_y, corner radi, type of index marker ]a
    my $extent = shift; # [ x sz incl. pins, dito y ] || for ix = 0, [ pad x center, pad y center ]

    #  optional
    # thermal: [ thermal pad x sz, y sz, via pitch, via drill ] || &drawing_function || string, jedec [ D1 or D2, E2 ]
    my $thermal = shift;
    my $pnum = shift;  # pin number at a pin position
    my $pname = shift; # pin pos. name

    ######
    my ($nx, $ny) = @$N;
    my $pitch = $$pin[0];

    #print " name:   $name $doc";
    #print " N:      [ $$N[0] $$N[1] ]\n";
    #print " pin:    [ $pitch $$pin[1] $$pin[2] ]\n";
    #print " body:   [ $$body[0] $$body[1] $$body[2] $$body[3] ]\n";
    #print " extent: [ $$extent[0] $$extent[1] ]\n";
    #print " therm.: [ $$thermal[0] $$thermal[1] ]\n" if (defined($thermal));
    #print " pnum:   ( ", join(" ", @$pnum), " )\n"   if (defined($pnum));
    #print " pname:  ( ", join(" ", @$pname), " )\n"  if (defined($pname));
    #print "\n";
    ######

    my $ipc_size_type = "S";
    if ($pitch >= 0.625) {
	$ipc_size_type = "L";
    }
    my @ipc_arr = @{$ipc{$ipc_size_type}};
    my $cr = 0;
    my @ix_list = ();
    if (defined($$pin[3])) {
	@ix_list = @$pin;
	splice( @ix_list, 0, 3);
    } else {
	@ix_list = (1..3);
    }

    my $body_min = $$body[0];
    if ($body_min > $$body[1]) { $body_min = $$body[1]; }
    my $index_marker = $$body[3];

    ### iterate over ipc level and corner radius
    for my $px (@ix_list) {
	my $suffix = $ipc_hdr[$px];
	my ($toe, $heel, $side, $roundoff, $courtyard) = @{$ipc_arr[$px]};
	#print "$toe, $heel, $side, $roundoff, $courtyard\n";
	my $pad_len = round($$pin[2] + $toe + $heel, $roundoff);
	my $pad_wid = round($$pin[1] + 2*$side     , $roundoff);
	my $pad_x;
	my $pad_y;
	if ($px == 0) {
	    $pad_x = $$extent[0];
	    $pad_y = $$extent[1];
	} else {
	    $pad_x = round($$extent[0]/2 + $toe - $pad_len/2, $roundoff);
	    $pad_y = round($$extent[1]/2 + $toe - $pad_len/2, $roundoff);
	}

	for my $cr ((0, ipc_corner($pad_wid))) {
	    my $file;
	    if ($cr) {
		$file = sprintf("%s%sr.fp", $name, $suffix);
	    } else {
		$file = sprintf("%s%s.fp", $name, $suffix);
	    }

	    element_start($file, $doc);

	    pkg_rect_pads($N, [ $pad_x, $pad_y ], [ $pitch, $pad_wid, $pad_len, $cr], $pnum, $pname );

	    if (!defined($thermal) || !defined($$thermal[0]) || !defined($$thermal[0])) {
		$thermal = [ 0, 0];
	    }
	    if ($$thermal[0] > 0 && $$thermal[1] > 0) {
		my @bb_first = @{$bounding_box[0]};
		my @bb_last  = @{$bounding_box[$#bounding_box]};
		# look at the cu part only
		@bb_first = ($bb_first[0]+$mask_gap, $bb_first[1]-$mask_gap, $bb_first[2]+$mask_gap, $bb_first[3]-$mask_gap);
		@bb_last  = ($bb_last [0]+$mask_gap, $bb_last [1]-$mask_gap, $bb_last [2]+$mask_gap, $bb_last [3]-$mask_gap);
		# TODO: isn't this for debugging only ??
		bb_show([@bb_first], [@bb_last]);

		# chk th.pad size
		my $str = "";
		if ($$N[0]) {	# pads along the top/bottom side
		    my $a = $$thermal[1]/2;
		    my $b = -$bb_last[3];
		    if ($b - $a < $minimum{thermal_to_pad_distance}) {
			$$thermal[1] = 2* ( $b - $minimum{thermal_to_pad_distance} );
			$str = $file;
		    }
		}
		if ($$N[1]) {	# pads along the left/rigth side
		    my $a = $$thermal[0]/2;
		    my $b = -$bb_first[1];
		    if ($b - $a < $minimum{thermal_to_pad_distance}) {
			$$thermal[0] = 2* ( $b - $minimum{thermal_to_pad_distance} );
			$str = $file;
		    }
		}
		if ($str) {
		    print "$str thermal pad shrunk\n";
		}
		pkg_thermal_pad($$thermal[0], $$thermal[1], $$thermal[2]);
		$index_marker = 0;
	    }

	    pkg_body_rect($body);

	    # indes mark
	    silk_width(0.18);
	    my @bbw = bb_enlarge($silk_w/2, @bounding_box);
	    @bbw = grep { $$_[4] > 0 } @bbw;
	    @bbw = sort { $$a[4] <=> $$b[4] } @bbw;
	    my $bb_one = $bbw[0]; # pad with the lowest pin number
	    my $bbc = [ ($$bb_one[1] + $$bb_one[0])/2, ($$bb_one[3] + $$bb_one[2])/2 ];
	    my $ipos = "";
	    if ($$bbc[0] < 0) {
		if    ($$bbc[1] < 0) { $ipos = 'tl'; } # top left
		elsif ($$bbc[1] >= 0) { $ipos = 'bl'; } # bottom left
	    } else {
		if    ($$bbc[1] < 0) { $ipos = 'tr'; } # top right
		elsif ($$bbc[1] >= 0) { $ipos = 'br'; } # bottom right
	    }

	    if (defined($index_marker)) {
		my $nn;
		if ($index_marker > 0) {
		    # beveled body: draw a line along the side as if the body is beveled
		    if      ($ipos eq 'tl') {
			# left side line
			silk_start(- $$body[0]/2 + $index_marker, -$$body[1]/2);
			$nn = silk_rline(0, $$body[1], \@bbw);
		    } elsif ($ipos eq 'br') {
			# right side line
			silk_start(  $$body[0]/2 - $index_marker, -$$body[1]/2);
			$nn = silk_rline(0, $$body[1], \@bbw);
		    } elsif ($ipos eq 'tr') {
			# top side line
			silk_start(- $$body[0]/2, - $$body[1]/2 + $index_marker);
			$nn = silk_rline($$body[0], 0, \@bbw);
		    } elsif ($ipos eq 'bl') {
			# bottom side line
 			silk_start(- $$body[0]/2,   $$body[1]/2 - $index_marker);
			$nn = silk_rline($$body[0], 0, \@bbw);
		    }
		} elsif ($index_marker < 0) {
		    # draw a triangle in the corner
		    my $hh = - $index_marker;
		    silk_width(0.12);

		    if      ($ipos eq 'tl') {
			silk_start( - $$body[0]/2, - $$body[1]/2 + $hh);
			$nn = silk_rline( $hh, - $hh, \@bbw);
		    } elsif ($ipos eq 'bl') {
			silk_start( - $$body[0]/2,   $$body[1]/2 - $hh);
			$nn = silk_rline( $hh,   $hh, \@bbw);
		    } elsif ($ipos eq 'tr') {
			silk_start(   $$body[0]/2 - $hh, $$body[1]/2);
			$nn = silk_rline( $hh,   $hh, \@bbw);
		    } elsif ($ipos eq 'br') {
			silk_start(   $$body[0]/2 - $hh, $$body[1]/2);
			$nn = silk_rline( $hh, - $hh, \@bbw);
		    }
		    silk_width();
		}
		if (defined($nn) && $nn < 1) {
		    # no line drawn, pads in the way, try the bb corner version instead
		    $index_marker = 0;
		}

		if ($index_marker == 0) {
		    # draw ouline around the first
		    if    ($ipos eq 'tl') { bb_tlcorner($bb_one); }
		    elsif ($ipos eq 'bl') { bb_blcorner($bb_one); }
		    elsif ($ipos eq 'tr') { bb_trcorner($bb_one); }
		    elsif ($ipos eq 'br') { bb_brcorner($bb_one); }
		}
	    } else {
		my $dd = $body_min/12;
		my $rr = $body_min/50;
		if ($rr < 0.3) { $rr = 0.3; }
		if ($dd < 1.0) {
		    # draw an U as some DIL packages have between pin 1 and last pin
		    # no bounding box checking
		    if ($ipos eq 'tl') {
			# top side U
			silk_start(-$rr, -$$body[1]/2);
			silk_rline(  0,  $dd);
			silk_start( $rr, -$$body[1]/2);
			silk_rline(  0,  $dd);
			silk_arc([ 0, -$$body[1]/2+$dd], $rr, 0, 180);
		    } elsif ($ipos eq 'bl') {
			# left side U
			silk_start(-$$body[0]/2, -$rr);
			silk_rline(  $dd, 0);
			silk_start(-$$body[0]/2,  $rr);
			silk_rline(  $dd, 0);
			silk_arc([ -$$body[0]/2+$dd, 0], $rr, 90, 180);
		    } elsif ($ipos eq 'br') {
			# bottom side u
			silk_start(-$rr,  $$body[1]/2);
			silk_rline(  0, -$dd);
			silk_start( $rr,  $$body[1]/2);
			silk_rline(  0, -$dd);
			silk_arc([ 0,  $$body[1]/2-$dd], $rr, 180, 180);
		    } elsif ($ipos eq 'tr') {
			# right side U
			silk_start( $$body[0]/2, -$rr);
			silk_rline( -$dd, 0);
			silk_start( $$body[0]/2,  $rr);
			silk_rline( -$dd, 0);
			silk_arc([  $$body[0]/2-$dd, 0], $rr, 270, 180);
		    }
		} else {
		    # draw a circle in the corner
		    # no bounding box checking
		    if ($ipos eq 'tl') {
			silk_circle([-$$body[0]/2+$dd, -$$body[1]/2+$dd], $rr);
		    } elsif ($ipos eq 'bl') {
			silk_circle([-$$body[0]/2+$dd,  $$body[1]/2-$dd], $rr);
		    } elsif ($ipos eq 'br') {
			silk_circle([ $$body[0]/2-$dd,  $$body[1]/2-$dd], $rr);
		    } elsif ($ipos eq 'tr') {
			silk_circle([ $$body[0]/2-$dd, -$$body[1]/2+$dd], $rr);
		    }
		}
	    }

	    silk_width();
	    element_stop();
	}
    }
}

sub gen_maxim_umax() {
    my $name = "uMAX_";
    my $doc = "# https/www.analog.com/media/en/package-pcb-resources/package/pkg_pdf/micromax/21-0061.pdf
# https/www.analog.com/media/en/package-pcb-resources/package/pkg_pdf/micromax/21-0036.pdf\n";

    my @data = (
#	  $N,  $D,   $E,    $H,   $L,    $b,   $e ) =
	[ 10, 3.00, 3.00, 4.90, 0.55, 0.223, 0.50 ],
	[  8, 3.00, 3.00, 4.90, 0.53, 0.300, 0.65 ],
    );
    for my $r (@data) {
	my ( $N, $D, $E, $H, $L, $b, $e ) = @$r;
	my $pfx = $name . $N;
	pkg_smdpinsR($pfx, $doc, [$N/2, 0], [$e, $b, $L], [$D, $E], [$D,$H]);
    }
}
#gen_maxim_umax();

sub gen_jedec_mo046() {
    my $name = "jedec_mo-046";
    # small outline (SO) package, wide body
    my $doc  = "# http://www.jedec.org/  Mo-046b.pdf\n";
    my (    $A,  $A1,   $B,   $C,   $E,   $e,   $H,   $L) =
	( 1.60, 0.10, 0.43, 0.15, 5.30, 1.27, 7.80, 0.50);

    my @data = (
	#  var      D    N
	[ "AA"  , 10.30, 14, ],
	[ "AB"  , 10.30, 16, ],
	[ "AC"  , 12.80, 20, ],
    );

    for my $r (@data) {
	my ($var, $D, $N, ) = @$r;
	my $pfx = $name . "-" . $var;
	pkg_smdpinsR($pfx, $doc, [$N/2, 0], [$e, $B, $L], [$D, $E], [$D,$H]);
    }
}
#gen_jedec_mo046();

sub gen_jedec_mo059() {
    my $name = "jedec_mo-059";
    # small outline (SO) package, with 8.4mm body width
    my $doc  = "# http://www.jedec.org/  Mo-059b.pdf\n";
    my (  $A1,   $B,  $B1,   $C,   $E,   $e,    $H,   $h,   $L) =
	(0.20, 0.43, 0.48, 0.23, 8.56, 1.27, 12.10, 0.50, 1.00);

    my @data = (
	#  var   A      D    N
	[ "AA", 2.29, 15.65, 24 ],
	[ "AB", 2.80, 15.65, 24 ],
	[ "AC", 2.29, 18.10, 28 ],
	[ "AD", 2.80, 18.10, 28 ],
    );

    for my $r (@data) {
	my ($var, $A, $D, $N) = @$r;
	my $pfx = $name . "-" . $var;
	pkg_smdpinsR($pfx, $doc, [$N/2, 0], [$e, $B, $L], [$D, $E, 0, $h], [$D,$H]);
    }
}
#gen_jedec_mo059();

sub gen_jedec_mo071() {
    my $name = "jedec_mo-071";
    # plastic thin lead package family, square (gullwing)
    my $doc  = "# http://www.jedec.org/  Mo-071b.pdf\n";
    my @data = (
	#  var     A    A1    A2       D     D1     D3      E     E1     E3    L1    L2    N      e    e1
	[ "AA", 1.98, 1.40, 0.15,   9.14,  7.26,  4.57,  9.14,  7.26,  4.57, 0.30, 0.69,  40, 0.508, 0.28 ],
	[ "AB", 2.17, 1.40, 0.15,  10.66,  8.78,  6.09, 10.71,  8.78,  6.09, 0.30, 0.69,  52, 0.508, 0.28 ],
	[ "AC", 2.17, 1.40, 0.15,  12.69, 10.81,  8.12, 12.69, 10.82,  8.12, 0.30, 0.69,  68, 0.508, 0.28 ],
	[ "AD", 2.17, 1.80, 0.15,  14.72, 12.82, 10.15, 14.72, 12.82, 10.15, 0.30, 0.69,  84, 0.508, 0.28 ],
	[ "AE", 2.41, 1.80, 0.38,  22.91, 20.45, 16.26, 22.91, 20.45, 16.26, 0.60, 0.84, 132, 0.508, 0.28 ],
	[ "AF", 2.41, 1.80, 0.38,  32.77, 30.61, 27.43, 32.61, 30.61, 27.43, 0.60, 0.84, 220, 0.508, 0.28 ],
	[ "BA", 2.41, 1.80, 0.38,  22.91, 20.45, 16.67, 22.91, 20.45, 16.67, 0.60, 0.84, 180, 0.381, 0.28 ],
	[ "BB", 2.41, 1.80, 0.38,  32.77, 30.61, 26.67, 32.61, 30.61, 26.67, 0.60, 0.84, 284, 0.381, 0.28 ],
    );
    for my $r (@data) {
	my ($var, $A, $A1, $A2, $D, $D1, $D3, $E, $E1, $E3, $L1, $L2, $N, $e, $e1) = @$r;
	my $pfx = $name . "-" . $var;
	pkg_smdpins($pfx, $doc, [$N/4, $N/4], [$e, $e1, $L2], [$D1, $E1, 0, -0.90], [$D,$E]);
    }
}
#gen_jedec_mo071();

sub gen_jedec_mo099() {
    my $name = "jedec_mo-099";
    # small outline (SO) package, 11.2mm body width
    my $doc  = "# http://www.jedec.org/  Mo-099a.pdf\n";
    my (   $A,  $A1,   $B,   $C,    $E,   $e,    $H,   $h,   $L) =
	(2.79, 0.22, 0.42, 0.23, 11.20, 1.27, 14.10, 0.50, 1.00);

    my @data = (
	#  var    D    N
	[ "AA", 18.00, 28 ],
	[ "AB", 20.50, 32 ],
    );

    for my $r (@data) {
	my ($var, $D, $N) = @$r;
	my $pfx = $name . "-" . $var;
	pkg_smdpinsR($pfx, $doc, [$N/2, 0], [$e, $B, $L], [$D, $E, $h], [$D,$H]);
    }
}
#gen_jedec_mo099();

sub gen_jedec_mo117() {
    my $name = "jedec_mo-117";
    # small outline (SO) package, 12mm body, 0.980mm lead spacing
    my $doc  = "# http://www.jedec.org/  Mo-117a.pdf\n";
    my (   $A,  $A1,   $B,  $B1,    $E,   $E1,   $L,  $L1,  $L2,   $e) =
	(2.10, 2.00, 0.37, 0.35, 14.25, 12.00, 1.12, 0.25, 0.50, 0.80);

    my @data = (
	#  var    D    N
	[ "AA", 26.30, 64 ],
    );

    for my $r (@data) {
	my ($var, $D, $N) = @$r;
	my $pfx = $name . "-" . $var;
	pkg_smdpinsR($pfx, $doc, [$N/2, 0], [$e, $B, $L2], [$D, $E1], [$D,$E]);
    }
}
#gen_jedec_mo117();

sub gen_jedec_mo118() {
    my $name = "jedec_mo-118";
    # shrink small outline package, .025"pitch, .300"  body width
    my $doc  = "# http://www.jedec.org/  Mo-118a.pdf\n";
    my (   $A,  $A1,   $b,  $b1,  $b2,   $c,  $c1,    $E,  $E1,   $e,   $h,   $L) =
	(2.60, 0.30, 0.28, 0.25, 0.30, 0.19, 0.17, 10.35, 7.49, 0.64, 0.51, 0.76);

    my @data = (
	#  var    D    N
	[ "AA", 15.88, 48 ],
	[ "AB", 18.42, 56 ],
	[ "AC",  9.52, 28 ],
	[ "AD", 20.96, 64 ],
    );

    for my $r (@data) {
	my ($var, $D, $N) = @$r;
	my $pfx = $name . "-" . $var;
	pkg_smdpinsR($pfx, $doc, [$N/2, 0], [$e, $b, $L], [$D, $E1], [$D,$E]);
    }
}
#gen_jedec_mo118();

sub gen_jedec_mo119() {
    my $name = "jedec_mo-119";
    # small outline (SO) package family with .300 inch body width
    my $doc  = "# http://www.jedec.org/  Mo-119b.pdf\n";
    my (    $A,  $A1,  $A2,  $b,   $b1,  $b2,   $c,  $c1,   $E,   $e,    $H,   $L,   $X) =
	( 2.64, 0.10, 2.24, 0.41, 0.41, 0.71, 0.20, 0.20, 7.52, 1.27, 10.46, 0.79, 0.36);


    my @data = (
	#  var    D     N
	[ "AA", 15.70, 24 ],
	[ "AB", 18.24, 28 ],
	[ "AC", 20.78, 32 ],
	[ "AD", 23.32, 36 ],
    );

    for my $r (@data) {
	my ($var, $D, $N) = @$r;
	my $pfx = $name . "-" . $var;
	pkg_smdpinsR($pfx, $doc, [$N/2, 0], [$e, $b, $L], [$D, $E], [$D,$H]);
    }
}
#gen_jedec_mo119();

sub gen_jedec_mo120() {
    my $name = "jedec_mo-120";
    # small outline (SO) package family with .350 inch body width
    my $doc  = "# http://www.jedec.org/  Mo-120b.pdf\n";
    my (    $A,  $A1,  $A2,  $b,   $b1,  $b2,   $c,  $c1,   $E,   $e,    $H,   $L,   $X) =
	( 2.64, 0.10, 2.24, 0.41, 0.41, 0.71, 0.20, 0.20, 8.89, 1.27, 11.99, 0.79, 0.36);


    my @data = (
	#  var    D     N
	[ "AA", 15.70, 24 ],
	[ "AB", 18.24, 28 ],
	[ "AC", 20.78, 32 ],
	[ "AD", 23.32, 36 ],
    );

    for my $r (@data) {
	my ($var, $D, $N) = @$r;
	my $pfx = $name . "-" . $var;
	pkg_smdpinsR($pfx, $doc, [$N/2, 0], [$e, $b, $L], [$D, $E], [$D,$H]);
    }
}
#gen_jedec_mo120();

sub gen_jedec_mo137() {
    my $name = "jedec_mo-137";
    # SSOP 0.025" pitch and 0.150" body
    my $doc  = "# http://www.jedec.org/  MO-137E.pdf\n";
    # $phi, $phi1, $phi2, $note, $ref, $issue skipped
    # Thermal bottom pad with dimensions D1 and E2 have wide margins, I use max values, check manufakturer
    my (  $A2,   $b,    $b1,   $c,    $c1,   $E,    $E1,   $e,    $L,    $L1,   $L2,   $R,    $R1,   $h,) =
	map { inch_to_mm($_) }
	( 0.049, 0.010, 0.010, 0.007, 0.006, 0.236, 0.154, 0.025, 0.050, 0.041, 0.010, 0.003, 0.003, 0.015);


    my @data = (
	#  var      A     A1     D      D1     E2     N
	[ "AA"  , 0.069, 0.005, 0.193, undef, undef, 14, ],
	[ "AB"  , 0.069, 0.005, 0.193, undef, undef, 16, ],
	[ "AC"  , 0.069, 0.005, 0.341, undef, undef, 18, ],
	[ "AD"  , 0.069, 0.005, 0.341, undef, undef, 20, ],
	[ "AE"  , 0.069, 0.005, 0.341, undef, undef, 24, ],
	[ "AF"  , 0.069, 0.005, 0.390, undef, undef, 28, ],
	[ "BA"  , 0.067, 0.002, 0.193, 0.090, 0.096, 14, ],
	[ "BA-1", 0.067, 0.002, 0.193, 0.130, 0.090, 14, ],
	[ "BB"  , 0.067, 0.002, 0.193, 0.090, 0.096, 16, ],
	[ "BB-1", 0.067, 0.002, 0.193, 0.130, 0.090, 16, ],
    );

    for my $r (@data) {
	my $var = shift @$r;
	my $N = pop @$r;
	my ($A, $A1, $D, $D1, $E2,) = map { defined($_) ? inch_to_mm($_) : $_ } @$r; # $note, $ref, $issue,
	my $pfx = $name . "-" . $var;
	pkg_smdpinsR($pfx, $doc, [$N/2, 0], [$e, $b, $L], [$D, $E1, 0, $h], [$D,$E], [$D1, $E2, 1]);
    }
}
#gen_jedec_mo137();

sub gen_jedec_mo142() {
    my $name = "jedec_mo-142";
    # TSOP type I
    my $doc  = "# http://www.jedec.org/  MO-142D.pdf\n";
    my (    $A,  $A1,  $A2,   $b,  $b1,   $c,  $c1,   $e,   $L,  $L1, ) =
	( 1.20, 0.10, 1.00, 0.22, 0.20, 0.15, 0.13, 0.50, 0.60, 0.25, );

    my @data = (
	#  var      D     D1      E     N
	[ "AA"  , 14.00, 12.40,  6.00, 24, ],
	[ "AB"  , 16.00, 14.40,  6.00, 24, ],
	[ "AC"  , 18.00, 16.40,  6.00, 24, ],
	[ "AD"  , 20.00, 18.40,  6.00, 24, ],

	[ "BA"  , 14.00, 12.40,  8.00, 32, ],
	[ "BB"  , 16.00, 14.40,  8.00, 32, ],
	[ "BC"  , 18.00, 16.40,  8.00, 32, ],
	[ "BD"  , 20.00, 18.40,  8.00, 32, ],

	[ "CA"  , 14.00, 12.40, 10.00, 40, ],
	[ "CB"  , 16.00, 14.40, 10.00, 40, ],
	[ "CC"  , 18.00, 16.40, 10.00, 40, ],
	[ "CD"  , 20.00, 18.40, 10.00, 40, ],

	[ "DA"  , 14.00, 12.40, 12.00, 48, ],
	[ "DB"  , 16.00, 14.40, 12.00, 48, ],
	[ "DC"  , 18.00, 16.40, 12.00, 48, ],
	[ "DD"  , 20.00, 18.40, 12.00, 48, ],

	[ "EA"  , 16.00, 14.40, 14.00, 56, ],
	[ "EB"  , 18.00, 16.40, 14.00, 56, ],
	[ "EC"  , 20.00, 18.40, 14.00, 56, ],
    );
    my $h = undef;
    my $E1 = undef;
    my $E2 = undef;

    for my $r (@data) {
	my ($var, $D, $D1, $E, $N, ) = @$r;
	my $pfx = $name . "-" . $var;
	pkg_smdpins($pfx, $doc, [0, $N/2], [$e, $b, $L], [$D1, $E, 0, $h], [$D,$E]);
    }
}
#gen_jedec_mo142();

sub gen_jedec_mo150() {
    my $name = "jedec_mo-150";
    # plastic shrink shmall outline package (SSOP) 5.3mm body width, 0.65mm pitch, 1.25mm lead length
    my $doc  = "# http://www.jedec.org/  Mo-150b.pdf\n";
    my (    $A,  $A1,  $A2,  $b,   $b1,   $c,  $c1,   $E,  $E1,   $e,   $L,  $L1) =
	( 2.00, 0.05, 1.75, 0.30, 0.30, 0.17, 0.15, 7.80, 5.30, 0.65, 0.75, 1.25);


    my @data = (
	#  var    D     N
	[ "AA",  3.00,  8 ],
	[ "AB",  6.20, 14 ],
	[ "AC",  6.20, 16 ],
	[ "AD",  7.20, 18 ],
	[ "AE",  7.20, 20 ],
	[ "AF",  8.20, 22 ],
	[ "AG",  8.20, 24 ],
	[ "AH", 10.20, 28 ],
	[ "AJ", 10.20, 30 ],
	[ "AK", 12.60, 38 ],
    );

    for my $r (@data) {
	my ($var, $D, $N) = @$r;
	my $pfx = $name . "-" . $var;
	pkg_smdpinsR($pfx, $doc, [$N/2, 0], [$e, $b, $L], [$D, $E1], [$D,$E]);
    }
}
#gen_jedec_mo150();

sub gen_jedec_mo152() {
    my $name = "jedec_mo-152";
    # plastic shrink shmall outline pkg
    my $doc  = "# http://www.jedec.org/  Mo-152c.pdf\n";
    my (    $A,  $A1,  $A2,  $L,    $R,  $R1,   $c,  $c1,  $L1) =
	( 2.00, 0.15, 1.60, 0.60, 0.09, 0.09, 0.15, 0.12, 1.00);

    my %gen = (
	# $e        $b   $b1
	0.65 => [ 0.25, 0.22 ],
	0.50 => [ 0.22, 0.20 ],
	0.40 => [ 0.18, 0.16 ],
    );

    my @data = (
	#  var      D     E1    E    e     N
	[ "AA"  ,  3.0, 4.4,  6.4, 0.65,  8 ],
	[ "AB-1",  5.0, 4.4,  6.4, 0.65, 14 ],
	[ "AB"  ,  5.0, 4.4,  6.4, 0.65, 16 ],
	[ "AC"  ,  6.5, 4.4,  6.4, 0.65, 20 ],
	[ "AD"  ,  7.8, 4.4,  6.4, 0.65, 24 ],
	[ "AE"  ,  9.7, 4.4,  6.4, 0.65, 28 ],

	[ "BA"  ,  5.0, 4.4,  6.4, 0.50, 20 ],
	[ "BB"  ,  6.5, 4.4,  6.4, 0.50, 24 ],
	[ "BC"  ,  7.8, 4.4,  6.4, 0.50, 28 ],
	[ "BD"  ,  9.7, 4.4,  6.4, 0.50, 36 ],

	[ "CA"  ,  5.0, 4.4,  6.4, 0.40, 24 ],
	[ "CB"  ,  6.4, 4.4,  6.4, 0.40, 32 ],
	[ "CC"  ,  7.8, 4.4,  6.4, 0.40, 36 ],
	[ "CD"  ,  9.7, 4.4,  6.4, 0.40, 48 ],

	[ "DA"  ,  7.8, 6.1,  8.1, 0.65, 24 ],
	[ "DB"  ,  9.7, 6.1,  8.1, 0.65, 28 ],
	[ "DB-1",  9.7, 6.1,  8.1, 0.65, 30 ],
	[ "DC"  , 11.0, 6.1,  8.1, 0.65, 32 ],
	[ "DD"  , 12.5, 6.1,  8.1, 0.65, 36 ],
	[ "DE"  , 14.0, 6.1,  8.1, 0.65, 40 ],

	[ "EA"  ,  7.8, 6.1,  8.1, 0.50, 28 ],
	[ "EB"  ,  9.7, 6.1,  8.1, 0.50, 36 ],
	[ "EC"  , 11.0, 6.1,  8.1, 0.50, 40 ],
	[ "EC-1", 11.0, 6.1,  8.1, 0.50, 44 ],
	[ "ED"  , 12.5, 6.1,  8.1, 0.50, 48 ],
	[ "EE"  , 14.0, 6.1,  8.1, 0.50, 56 ],
	[ "EF"  , 17.0, 6.1,  8.1, 0.50, 64 ],

	[ "FA"  ,  7.8, 6.1,  8.1, 0.40, 36 ],
	[ "FB"  ,  9.7, 6.1,  8.1, 0.40, 48 ],
	[ "FC"  , 11.0, 6.1,  8.1, 0.40, 52 ],
	[ "FD"  , 12.5, 6.1,  8.1, 0.40, 56 ],
	[ "FE"  , 14.0, 6.1,  8.1, 0.40, 64 ],
	[ "FF"  , 17.0, 6.1,  8.1, 0.40, 80 ],

	[ "GA"  ,  9.7, 8.0, 10.0, 0.65, 28 ],
	[ "GB"  , 11.0, 8.0, 10.0, 0.65, 32 ],
	[ "GC"  , 12.5, 8.0, 10.0, 0.65, 36 ],
	[ "GD"  , 14.0, 8.0, 10.0, 0.65, 40 ],

	[ "HA"  ,  9.7, 8.0, 10.0, 0.50, 36 ],
	[ "HB"  , 11.0, 8.0, 10.0, 0.50, 40 ],
	[ "HC"  , 12.5, 8.0, 10.0, 0.50, 48 ],
	[ "HD"  , 14.0, 8.0, 10.0, 0.50, 56 ],

	[ "JA"  ,  9.7, 8.0, 10.0, 0.40, 48 ],
	[ "JB"  , 11.0, 8.0, 10.0, 0.40, 52 ],
	[ "JC"  , 12.5, 8.0, 10.0, 0.40, 56 ],
	[ "JC-1", 12.5, 8.0, 10.0, 0.40, 60 ],
	[ "JD"  , 14.0, 8.0, 10.0, 0.40, 64 ],
	[ "JD-1", 14.0, 8.0, 10.0, 0.40, 68 ],
    );

    for my $r (@data) {
	my ($var, $D, $E1, $E, $e, $N) = @$r;
	my ($b, $b1) = @{$gen{$e}};
	my $pfx = $name . "-" . $var;
	pkg_smdpinsR($pfx, $doc, [$N/2, 0], [$e, $b, $L], [$D, $E1], [$D,$E]);
    }
}
#gen_jedec_mo152();

sub gen_jedec_mo153() {
    my $name = "jedec_mo-153";
    # TSSOP
    my $doc  = "# http://www.jedec.org/  MO-153G.pdf\n";

    my $h = undef;
    my $L = 0.60;
    my @data = (
	#   $e,   $b, $var,     $A1,    $D,   $D1,    $E,  $E1,   $E2,  $SD,  $N
	# table 3
	[ 0.40, 0.18, "CA",    0.10,  5.00, undef,  6.40, 4.40, undef, 0.20,  24 ],
	[ 0.40, 0.18, "CB",    0.10,  6.50, undef,  6.40, 4.40, undef, 0.20,  32 ],
	[ 0.40, 0.18, "CC",    0.10,  7.80, undef,  6.40, 4.40, undef, 0.20,  36 ],
	[ 0.40, 0.18, "CD",    0.10,  9.70, undef,  6.40, 4.40, undef, 0.20,  48 ],
	# table 4
	[ 0.40, 0.18, "FA",    0.10,  7.80, undef,  8.10, 6.10, undef, 0.20,  36 ],
	[ 0.40, 0.18, "FB",    0.10,  9.70, undef,  8.10, 6.10, undef, 0.20,  48 ],
	[ 0.40, 0.18, "FC",    0.10, 11.00, undef,  8.10, 6.10, undef, 0.20,  52 ],
	[ 0.40, 0.18, "FD",    0.10, 12.50, undef,  8.10, 6.10, undef, 0.20,  56 ],
	[ 0.40, 0.18, "FE",    0.10, 14.00, undef,  8.10, 6.10, undef, 0.20,  64 ],
	[ 0.40, 0.18, "FF",    0.10, 17.00, undef,  8.10, 6.10, undef, 0.20,  80 ],
	# table 5
	[ 0.40, 0.18, "JA",    0.10,  9.70, undef, 10.00, 8.00, undef, 0.20,  48 ],
	[ 0.40, 0.18, "JB",    0.10, 11.00, undef, 10.00, 8.00, undef, 0.20,  52 ],
	[ 0.40, 0.18, "JC",    0.10, 12.50, undef, 10.00, 8.00, undef, 0.20,  56 ],
	[ 0.40, 0.18, "JC-1",  0.10, 12.50, undef, 10.00, 8.00, undef, 0.20,  60 ],
	[ 0.40, 0.18, "JD",    0.10, 14.00, undef, 10.00, 8.00, undef, 0.20,  64 ],
	[ 0.40, 0.18, "JD-1",  0.10, 14.00, undef, 10.00, 8.00, undef, 0.20,  68 ],
	# table 6
	[ 0.50, 0.22, "BA",    0.10,  5.00, undef,  6.40, 4.40, undef, 0.25,  20 ],
	[ 0.50, 0.22, "BB",    0.10,  6.50, undef,  6.40, 4.40, undef, 0.25,  24 ],
	[ 0.50, 0.22, "BC",    0.10,  7.80, undef,  6.40, 4.40, undef, 0.25,  28 ],
	[ 0.50, 0.22, "BC-1",  0.10,  7.80, undef,  6.40, 4.40, undef, 0.25,  30 ],
	[ 0.50, 0.22, "BD",    0.10,  9.70, undef,  6.40, 4.40, undef, 0.25,  36 ],
	[ 0.50, 0.22, "BD-1",  0.10,  9.70, undef,  6.40, 4.40, undef, 0.00,  38 ],
	[ 0.50, 0.22, "BE",    0.10, 11.00, undef,  6.40, 4.40, undef, 0.25,  44 ],
	[ 0.50, 0.22, "BF",    0.10, 12.60, undef,  6.40, 4.40, undef, 0.25,  50 ],
	# table 7
	[ 0.50, 0.22, "EA",    0.10,  7.80, undef,  8.10, 6.10, undef, 0.25,  28 ],
	[ 0.50, 0.22, "EB",    0.10,  9.70, undef,  8.10, 6.10, undef, 0.25,  36 ],
	[ 0.50, 0.22, "EC",    0.10, 11.00, undef,  8.10, 6.10, undef, 0.25,  40 ],
	[ 0.50, 0.22, "EC-1",  0.10, 11.00, undef,  8.10, 6.10, undef, 0.25,  44 ],
	[ 0.50, 0.22, "ED",    0.10, 12.50, undef,  8.10, 6.10, undef, 0.25,  48 ],
	[ 0.50, 0.22, "EE",    0.10, 14.00, undef,  8.10, 6.10, undef, 0.25,  56 ],
	[ 0.50, 0.22, "EF",    0.10, 17.00, undef,  8.10, 6.10, undef, 0.25,  64 ],
	# table 8
	[ 0.50, 0.22, "HA",    0.10,  9.70, undef, 10.00, 8.00, undef, 0.25,  36 ],
	[ 0.50, 0.22, "HB",    0.10, 11.00, undef, 10.00, 8.00, undef, 0.25,  40 ],
	[ 0.50, 0.22, "HC",    0.10, 12.50, undef, 10.00, 8.00, undef, 0.25,  48 ],
	[ 0.50, 0.22, "HD",    0.10, 14.00, undef, 10.00, 8.00, undef, 0.25,  56 ],
	# table 9
	[ 0.65, 0.24, "AA",    0.10,  3.00, undef,  6.40, 4.40, undef, 0.325,  8 ],
	[ 0.65, 0.24, "AB",    0.10,  5.00, undef,  6.40, 4.40, undef, 0.325, 16 ],
	[ 0.65, 0.24, "AB-1",  0.10,  5.00, undef,  6.40, 4.40, undef, 0.000, 14 ],
	[ 0.65, 0.24, "AC",    0.10,  6.50, undef,  6.40, 4.40, undef, 0.325, 20 ],
	[ 0.65, 0.24, "AD",    0.10,  7.80, undef,  6.40, 4.40, undef, 0.325, 24 ],
	[ 0.65, 0.24, "AE",    0.10,  9.70, undef,  6.40, 4.40, undef, 0.325, 28 ],
	# table 10
	[ 0.65, 0.24, "DA",    0.10,  7.80, undef,  8.10, 6.10, undef, 0.325, 24 ],
	[ 0.65, 0.24, "DB",    0.10,  9.70, undef,  8.10, 6.10, undef, 0.325, 28 ],
	[ 0.65, 0.24, "DB-1",  0.10,  9.70, undef,  8.10, 6.10, undef, 0.000, 30 ],
	[ 0.65, 0.24, "DC",    0.10, 11.00, undef,  8.10, 6.10, undef, 0.325, 32 ],
	[ 0.65, 0.24, "DD",    0.10, 12.50, undef,  8.10, 6.10, undef, 0.325, 36 ],
	[ 0.65, 0.24, "DD-1",  0.10, 12.50, undef,  8.10, 6.10, undef, 0.000, 38 ],
	[ 0.65, 0.24, "DE",    0.10, 14.00, undef,  8.10, 6.10, undef, 0.325, 40 ],
	# table 11
	[ 0.65, 0.24, "GA",    0.10,  9.70, undef, 10.00, 8.00, undef, 0.325, 28 ],
	[ 0.65, 0.24, "GB",    0.10, 11.00, undef, 10.00, 8.00, undef, 0.325, 32 ],
	[ 0.65, 0.24, "GC",    0.10, 12.50, undef, 10.00, 8.00, undef, 0.325, 36 ],
	[ 0.65, 0.24, "GD",    0.10, 14.00, undef, 10.00, 8.00, undef, 0.325, 40 ],
	# table 12, D1 and E1 are minimum values
	[ 0.40, 0.18, "CAT",   0.10,  5.00,  1.70,  6.40, 4.40,  1.50, 0.20,  24 ],
	[ 0.40, 0.18, "CBT",   0.10,  6.50,  2.20,  6.40, 4.40,  1.50, 0.20,  32 ],
	[ 0.40, 0.18, "CCT",   0.10,  7.80,  2.70,  6.40, 4.40,  1.50, 0.20,  36 ],
	[ 0.40, 0.18, "CDT",   0.10,  9.70,  3.30,  6.40, 4.40,  1.50, 0.20,  48 ],
	# table 13
	[ 0.40, 0.18, "FAT",   0.10,  7.80,  2.70,  8.10, 6.10,  2.10, 0.20,  36 ],
	[ 0.40, 0.18, "FBT",   0.10,  9.70,  3.30,  8.10, 6.10,  2.10, 0.20,  48 ],
	[ 0.40, 0.18, "FCT",   0.10, 11.00,  3.80,  8.10, 6.10,  2.10, 0.20,  52 ],
	[ 0.40, 0.18, "FDT",   0.10, 12.50,  4.30,  8.10, 6.10,  2.10, 0.20,  56 ],
	[ 0.40, 0.18, "FET",   0.10, 14.00,  4.90,  8.10, 6.10,  2.10, 0.20,  64 ],
	[ 0.40, 0.18, "FFT",   0.10, 17.00,  5.90,  8.10, 6.10,  2.10, 0.20,  80 ],
	# table 14
	[ 0.40, 0.18, "JAT",   0.10,  9.70,  3.30, 10.00, 8.00,  2.80, 0.20,  48 ],
	[ 0.40, 0.18, "JBT",   0.10, 11.00,  3.80, 10.00, 8.00,  2.80, 0.20,  52 ],
	[ 0.40, 0.18, "JCT",   0.10, 12.50,  5.90, 10.00, 8.00,  2.80, 0.20,  56 ],
	[ 0.40, 0.18, "JCT-1", 0.10, 12.50,  5.90, 10.00, 8.00,  2.80, 0.20,  60 ],
	[ 0.40, 0.18, "JDT",   0.10, 14.00,  4.90, 10.00, 8.00,  2.80, 0.20,  64 ],
	[ 0.40, 0.18, "JDT-1", 0.10, 14.00,  4.90, 10.00, 8.00,  2.80, 0.20,  68 ],
	# table 15
	[ 0.50, 0.22, "BAT",   0.10,  5.00,  1.70,  6.40, 4.40,  1.50, 0.25,  20 ],
	[ 0.50, 0.22, "BBT",   0.10,  6.50,  2.20,  6.40, 4.40,  1.50, 0.25,  24 ],
	[ 0.50, 0.22, "BCT",   0.10,  7.80,  2.70,  6.40, 4.40,  1.50, 0.25,  28 ],
	[ 0.50, 0.22, "BCT-1", 0.10,  7.80,  2.70,  6.40, 4.40,  1.50, 0.00,  30 ],
	[ 0.50, 0.22, "BDT",   0.10,  9.70,  3.30,  6.40, 4.40,  1.50, 0.25,  36 ],
	[ 0.50, 0.22, "BDT-1", 0.10,  9.70,  3.30,  6.40, 4.40,  1.50, 0.00,  38 ],
	[ 0.50, 0.22, "BET",   0.10, 11.00,  3.80,  6.40, 4.40,  1.50, 0.25,  44 ],
	[ 0.50, 0.22, "BFT",   0.10, 12.60,  4.30,  6.40, 4.40,  1.50, 0.00,  50 ],
	# table 16
	[ 0.50, 0.22, "EAT",   0.10,  7.80,  2.70,  8.10, 6.10,  2.10, 0.25,  28 ],
	[ 0.50, 0.22, "EBT",   0.10,  9.70,  3.30,  8.10, 6.10,  2.10, 0.25,  36 ],
	[ 0.50, 0.22, "ECT",   0.10, 11.00,  3.80,  8.10, 6.10,  2.10, 0.25,  40 ],
	[ 0.50, 0.22, "ECT-1", 0.10, 11.00,  3.80,  8.10, 6.10,  2.10, 0.25,  44 ],
	[ 0.50, 0.22, "EDT",   0.10, 12.50,  4.30,  8.10, 6.10,  2.10, 0.25,  48 ],
	[ 0.50, 0.22, "EET",   0.10, 14.00,  4.90,  8.10, 6.10,  2.10, 0.25,  56 ],
	[ 0.50, 0.22, "EFT",   0.10, 17.00,  5.90,  8.10, 6.10,  2.10, 0.25,  64 ],
	# table 17
	[ 0.50, 0.22, "HAT",   0.10,  9.70,  3.30, 10.00, 8.00,  2.80, 0.25,  36 ],
	[ 0.50, 0.22, "HBT",   0.10, 11.00,  3.80, 10.00, 8.00,  2.80, 0.25,  40 ],
	[ 0.50, 0.22, "HCT",   0.10, 12.50,  5.90, 10.00, 8.00,  2.80, 0.25,  48 ],
	[ 0.50, 0.22, "HDT",   0.10, 14.00,  4.90, 10.00, 8.00,  2.80, 0.25,  56 ],
	# table 18
	[ 0.65, 0.24, "AAT",   0.08,  3.00,  1.00,  6.40, 4.40,  1.50, 0.325,  8 ],
	[ 0.65, 0.24, "ABT",   0.08,  5.00,  1.70,  6.40, 4.40,  1.50, 0.325, 16 ],
	[ 0.65, 0.24, "ABT-1", 0.08,  5.00,  1.70,  6.40, 4.40,  1.50, 0.325, 14 ],
	[ 0.65, 0.24, "ACT",   0.08,  6.50,  2.20,  6.40, 4.40,  1.50, 0.325, 20 ],
	[ 0.65, 0.24, "ADT",   0.08,  7.80,  2.70,  6.40, 4.40,  1.50, 0.325, 24 ],
	[ 0.65, 0.24, "AET",   0.08,  9.70,  3.30,  6.40, 4.40,  1.50, 0.325, 28 ],
	# table 19
	[ 0.65, 0.24, "DAT",   0.08,  7.80,  2.70,  8.10, 6.10,  2.10, 0.325, 24 ],
	[ 0.65, 0.24, "DBT",   0.08,  9.70,  3.30,  8.10, 6.10,  2.10, 0.325, 28 ],
	[ 0.65, 0.24, "DBT-1", 0.08,  9.70,  3.30,  8.10, 6.10,  2.10, 0.000, 30 ],
	[ 0.65, 0.24, "DCT",   0.08, 11.00,  3.80,  8.10, 6.10,  2.10, 0.325, 32 ],
	[ 0.65, 0.24, "DDT",   0.08, 12.50,  4.30,  8.10, 6.10,  2.10, 0.325, 36 ],
	[ 0.65, 0.24, "DDT-1", 0.08, 12.50,  4.30,  8.10, 6.10,  2.10, 0.000, 38 ],
	[ 0.65, 0.24, "DET",   0.08, 14.00,  4.90,  8.10, 6.10,  2.10, 0.325, 40 ],
	# table 20
	[ 0.65, 0.24, "GAT",   0.08,  9.70,  3.30, 10.00, 8.00,  2.80, 0.325, 28 ],
	[ 0.65, 0.24, "GBT",   0.08, 11.00,  4.90, 10.00, 8.00,  2.80, 0.325, 32 ],
	[ 0.65, 0.24, "GCT",   0.08, 12.50,  4.30, 10.00, 8.00,  2.80, 0.325, 36 ],
	[ 0.65, 0.24, "GDT",   0.08, 14.00,  4.90, 10.00, 8.00,  2.80, 0.325, 40 ],
    );

    for my $r (@data) {
	my ($e,   $b, $var,   $A1,   $D,   $D1,   $E,  $E1,   $E2,  $SD, $N) =  @$r;
	my $pfx = $name . "-" . $var;
	pkg_smdpinsR($pfx, $doc, [$N/2, 0], [$e, $b, $L], [$D, $E1, 0, $h], [$D,$E], [$D1, $E2, 1]);
    }
}
#gen_jedec_mo153();

sub gen_jedec_mo154() {
    my $name = "jedec_mo-154";
    # shrink small outline pkg family, 3.9mm wide body
    my $doc  = "# http://www.jedec.org/  MO-154c.pdf\n";
    my (    $A,  $A1,  $A2,   $c,  $c1,   $E,  $E1,   $L,  $L1) =
	( 2.00, 0.25, 1.60, 0.15, 0.13, 6.00, 3.90, 0.60, 0.25);

    my @data = (
	#  var   $b    $b1    $D    $ZD    $e  $N
	[ "AA", 0.18, 0.16,  8.65, 0.525, 0.40, 40 ],
	[ "AB", 0.18, 0.16,  9.90, 0.350, 0.40, 48 ],
	[ "AC", 0.18, 0.16, 20.50, 0.850, 0.40, 96 ],

	[ "BA", 0.22, 0.20,  8.65, 0.575, 0.50, 32 ],
	[ "BB", 0.22, 0.20,  9.90, 0.200, 0.50, 40 ],
	[ "BC", 0.22, 0.20, 20.50, 0.500, 0.50, 80 ],
    );

    for my $r (@data) {
	my ($var, $b, $b1, $D, $ZD, $e, $N) = @$r;
	my $pfx = $name . "-" . $var;
	pkg_smdpinsR($pfx, $doc, [$N/2, 0], [$e, $b, $L], [$D, $E1], [$D,$E]);
    }
}
#gen_jedec_mo154();

sub gen_jedec_mo155() {
    my $name = "jedec_mo-155";
    # small outline plastic (sop) pkg.
    my $doc  = "# http://www.jedec.org/  Mo-155a.pdf\n";
    my  ( $A,   $A1,  $A2,   $b,  $b1,   $c,  $c1,   $D,   $E,   $e,  $e1,   $H,   $L) =
	(3.00, 0.10, 2.50, 0.42, 0.40, 0.16, 0.15, 3.60, 4.40, 1.27, 2.54, 7.00, 0.80);
    my ($var, $N)  = ("AA", 6);

    my $pfx = $name . "-" . $var;
    pkg_smdpinsR($pfx, $doc, [$N/2, 0], [$e, $b, $L], [$D, $E], [$D,$H], undef, [ 1, undef, 2 .. 5]);
}
#gen_jedec_mo155();

sub gen_jedec_mo180() {
    my $name = "jedec_mo-180";
    # SOP with 13.30mm body
    my $doc  = "# http://www.jedec.org/ MO-180b.pdf\n";
    my $D1 = undef;
    my $E2 = undef;
    my $h = undef;
    my @data = (
	# note ref issue are skipped
	# Thermal bottom pad with dimensions D1 and E2 have wide margins, I use max values, check manufakturer
	#  var      A    A1    A2    b     b1    c     c1     D      E      E1    e     L     N
	[ "AA"  , 2.80, 0.25, 2.30, 0.42, 0.40, 0.16, 0.15, 28.30, 16.00, 13.30, 1.27, 0.80, 44, ],
	[ "BA"  , 2.00, 0.55, 1.25, 0.37, 0.35, 0.16, 0.15, 23.70, 16.00, 13.30, 0.80, 0.80, 56, ],
	[ "CA"  , 1.90, 0.50, 1.25, 0.22, 0.20, 0.16, 0.15, 23.70, 16.00, 13.30, 0.50, 0.80, 90, ],
    );

    for my $r (@data) {
	my ( $var, $A, $A1, $A2, $b, $b1, $c, $c1, $D, $E, $E1, $e, $L, $N, ) = @$r;
	my $pfx = $name . "-" . $var;
	pkg_smdpinsR($pfx, $doc, [$N/2, 0], [$e, $b, $L], [$D, $E1], [$D,$E]);
    }
}
#gen_jedec_mo180();

sub gen_jedec_mo187() {
    my $name = "jedec_mo-187";
    # TSSOP 0.50 and 0.65 pitch
    my $doc  = "# http://www.jedec.org/  mo-187f.pdf\n";
    my $h = undef;
    my @data = (
	# note ref issue are skipped
	# Thermal bottom pad with dimensions D1 and E2 have wide margins, I use max values, check manufakturer
	#  var      A     A2    b     b1    D     D1    E     E1     E2    e     e1    L     L1    L2    N   ddd
	[ "AA"  , 1.10, 0.85, 0.30, 0.30, 3.00, undef, 4.90, 3.00, undef, 0.65, 1.95, 0.60, 0.95, 0.25,  8, 0.13, ],
	[ "BA"  , 1.10, 0.85, 0.25, 0.20, 3.00, undef, 4.90, 3.00, undef, 0.50, 2.00, 0.60, 0.95, 0.25, 10, 0.08, ],
	[ "AA-T", 1.10, 0.85, 0.30, 0.30, 3.00,  2.50, 4.90, 3.00,  2.50, 0.65, 1.95, 0.60, 0.95, 0.25,  8, 0.13, ],
	[ "BA-T", 1.10, 0.85, 0.25, 0.20, 3.00,  2.50, 4.90, 3.00,  2.50, 0.50, 2.00, 0.60, 0.95, 0.25, 10, 0.08, ],
	[ "CA"  , 1.10, 0.70, 0.25, 0.20, 2.00, undef, 3.10, 2.30, undef, 0.50, 1.50, 0.28, 0.40, 0.12,  8, 0.08, ],
	[ "DA"  , 1.10, 1.10, 0.23, 0.20, 2.95, undef, 4.00, 2.80, undef, 0.65, 1.95, 0.40, 0.60, 0.25,  8, 0.13, ],
    );

    for my $r (@data) {
	my ($var, $A, $A2, $b, $b1, $D, $D1, $E, $E1, $E2, $e, $e1, $L, $L1, $L2, $N, $ddd,) = @$r; # $note, $ref, $issue,
	my $pfx = $name . "-" . $var;
	pkg_smdpinsR($pfx, $doc, [$N/2, 0], [$e, $b, $L], [$D, $E1], [$D,$E], [$D1, $E2]);
    }
}
#gen_jedec_mo187();

sub gen_jedec_mo193() {
    my $name = "jedec_mo-193";
    # plastic thin shrink small outline package (shrink sot)
    my $doc  = "# http://www.jedec.org/  MO-193E.pdf\n";
    my $D1 = undef;
    my $E2 = undef;
    my $h = undef;
    my  ( $A,   $A1,  $A2 , $c,   $c1,  $D,   $E,   $E1,  $L,   $L1,  $L2,  $R,   $R1) =
	(1.10, 0.05, 0.90, 0.14, 0.13, 2.90, 2.80, 1.60, 0.45, 0.60, 0.25, 0.10, 0.17);
    my @data = (
	# $var,  $b,   $b1,  $e,   $e1, $N
	[ "AA", 0.40, 0.40, 0.95, 1.90, 6, ],
	[ "AB", 0.40, 0.40, 0.95, 1.90, 6, undef, [ 1..4, undef, 5 ] ], # note 6, pin at pos.5 removed
	[ "BA", 0.30, 0.30, 0.65, 1.95, 8, ],
    );

    for my $r (@data) {
	my ($var,  $b,   $b1,  $e,   $e1, $N, $rname, $rnum) = @$r;
	my $pfx = $name . "-" . $var;
	pkg_smdpinsR($pfx, $doc, [$N/2, 0], [$e, $b, $L], [$D, $E1, 0, 0], [$D,$E], undef, $rnum);
    }
}
#gen_jedec_mo193();

sub gen_jedec_mo194() {
    my $name = "jedec_mo-194";
    # plastic thin shrink small outline package 0.40 mm lead pitch
    my $doc  = "# http://www.jedec.org/  mo-194b.pdf\n";
    my $D1 = undef;
    my $E2 = undef;
    my $h = undef;
    my  ( $A,   $A2,   $b,  $b1,   $c,  $c1,   $e, $L,   $L1,    $R,  $R1) =
	(1.20, 1.00, 0.18, 0.16, 0.14, 0.13, 0.40, 0.60, 1.00, 0.09, 0.09);
    my @data = (
	# $var,   $A1,    $D,  $D1,    $E,  $E1,   $E2,   $e,  $N
	[ "AA" , 0.10,  3.60, undef, 6.40, 4.40, undef, 0.40,  14 ],
	[ "AB" , 0.10,  3.60, undef, 6.40, 4.40, undef, 0.40,  16 ],
	[ "AC" , 0.10,  5.00, undef, 6.40, 4.40, undef, 0.40,  20 ],
	[ "AF" , 0.10, 11.30, undef, 6.40, 4.40, undef, 0.40,  56 ],
	[ "BB" , 0.10, 20.80, undef, 8.10, 6.10, undef, 0.40, 100 ],
	[ "AAT", 0.10,  3.60,  1.20, 6.40, 4.40,  1.50, 0.40,  14 ],
	[ "ABT", 0.10,  3.60,  1.20, 6.40, 4.40,  1.50, 0.40,  16 ],
	[ "ACT", 0.10,  5.00,  1.70, 6.40, 4.40,  1.50, 0.40,  20 ],
	[ "AFT", 0.10, 11.30,  3.90, 6.40, 4.40,  1.50, 0.40,  56 ],
	[ "BBT", 0.10, 20.80,  7.20, 8.10, 6.10,  2.10, 0.40, 100 ],
    );

    for my $r (@data) {
	my ($var, $A1, $D, $D1, $E, $E1, $E2, $e, $N) = @$r;
	my $pfx = $name . "-" . $var;
	pkg_smdpinsR($pfx, $doc, [$N/2, 0], [$e, $b, $L], [$D, $E1], [$D,$E], [$D1, $E2, 1]);
    }
}
#gen_jedec_mo194();

sub gen_jedec_mo203() {
    my $name = "jedec_mo-203";
    # plastic thin shrink small outline package (shrink sot)
    my $doc  = "# http://www.jedec.org/  MO-203C.pdf\n";
    my $D1 = undef;
    my $E2 = undef;
    my $h = undef;
    my  ( $A,   $A1,  $A2 , $c,   $c1,  $D,   $E,   $E1,  $L,   $L1,  $L2,  $R,   $R1) =
	(1.10, 0.05, 0.90, 0.15, 0.13, 2.00, 2.10, 1.25, 0.36, 0.42, 0.15, 0.10, 0.17);
    my @data = (
	# $var,  $b,   $b1,  $e,   $e1, $N
	[ "AA", 0.23, 0.20, 0.65, 1.30, 6, undef, [ 1..4, undef, 5 ]], # note 6, pin at pos.5 removed
	[ "AB", 0.23, 0.20, 0.65, 1.30, 6, ],
	[ "BA", 0.21, 0.18, 0.50, 1.50, 8, ],
    );

    for my $r (@data) {
	my ($var,  $b,   $b1,  $e,   $e1, $N, $rname, $rnum) = @$r;
	my $pfx = $name . "-" . $var;
	pkg_smdpinsR($pfx, $doc, [$N/2, 0], [$e, $b, $L], [$D, $E1, 0, 0], [$D,$E], undef, $rnum);
    }
}
#gen_jedec_mo203();

sub gen_jedec_mo212() {
    my $name = "jedec_mo-212";
    # rectangular plastic quad flat package outline
    my $doc  = "# http://www.jedec.org/  mo-212a.pdf\n";
    my $E2 = undef;
    my $h = undef;
    my $var = "AA";
    my  ( $A,   $A1,  $A2,   $b,  $b1,   $c,  $c1,    $D,   $D1,   $e,    $E,   $E1,   $L,  $L1,  $N, $ND, $NE) =
	(1.20, 0.10, 1.00, 0.31, 0.30, 0.17, 0.15, 23.20, 20.00, 0.65, 17.20, 14.00, 0.88, 1.60, 100,  30,  20);
    my @N = ( $ND, $ND+$NE, $ND+$NE+$ND, $ND+$NE+$ND+$NE);
    my $pfx = $name . "-" . $var;
    pkg_smdpinsR($pfx, $doc, [$ND, $NE], [$e, $b, $L], [$D1, $E1], [$D,$E]);
}
#gen_jedec_mo212();

sub gen_jedec_mo220() {
    my $name = "jedec_mo-220";
    # Thermally enhanced plastic very thin and very very thin fine pitch quad flat no lead package
    my $doc  = "# http://www.jedec.org/  MO-220K01.pdf\n";

    # table 1 p3
    my %var1 = ( # 1st letter: A
	V => 1.00,
	W => 0.80,
    );
    my %var2 = ( # second and third: D E
	A =>  1.0,
	B =>  1.5,
	C =>  2.0,
	D =>  2.5,
	E =>  3.0,
	F =>  3.5,
	G =>  4.0,
	H =>  5.0,
	J =>  6.0,
	K =>  7.0,
	L =>  8.0,
	M =>  9.0,
	N => 10.0,
	P => 11.0,
	R => 12.0,
	S =>  4.5,
	T =>  5.5,
	U =>  6.5,
    );
    my %var4 = ( # 4th letter: e
	A => 1.00,
	B => 0.80,
	C => 0.65,
	D => 0.50,
	E => 0.40,
    );

    # common dim. table 2, p4
    my %A = (  # A => A2
	0.90 => 0.65,
	0.75 => 0.55,
    );
    my  ( $A1, $A3, $L1, $K ) = ( 0.03, 0.20, 0.8, 0.20 );
    # $R = $b/2 or 0

    # table 3 p4
    my %b = ( # e => b
	1.00 => 0.40,
	0.80 => 0.30,
	0.65 => 0.30,
	0.50 => 0.25,
	0.40 => 0.20,
    );

    my @data = ( # talbe 6A ..
	# $var,         D2     E2    L   ND  NE
	# e = 0.80
	[ "VEEB"   ,   0.70,  0.70, 0.55,  1,  1 ],
	[ "VGEB"   ,   1.70,  0.70, 0.55,  3,  1 ],
	[ "VGGB"   ,   1.70,  1.70, 0.55,  3,  3 ],
	[ "VGGB-1" ,   2.20,  2.20, 0.55,  4,  3 ],
	[ "VGHB"   ,   2.20,  3.20, 0.55,  2,  3 ],
	[ "VHGB"   ,   2.70,  1.70, 0.55,  4,  3 ],
	[ "VHGB-1" ,   3.20,  2.20, 0.55,  5,  3 ],
	[ "VHHB"   ,   2.70,  2.70, 0.55,  4,  4 ],

	[ "VHHB-1" ,   3.20,  3.20, 0.55,  6,  4 ],
	[ "VJHB"   ,   3.70,  2.70, 0.55,  5,  4 ],
	[ "VJHB-1" ,   4.20,  3.20, 0.55,  6,  4 ],
	[ "VJJB"   ,   3.70,  3.70, 0.55,  5,  5 ],
	[ "VJJB-1" ,   4.20,  4.20, 0.55,  7,  5 ],
	[ "VJJB-2" ,   4.20,  4.20, 0.55,  5,  7 ],
	[ "VKKB"   ,   4.70,  4.70, 0.55,  7,  7 ],
	[ "VLLB"   ,   5.70,  5.70, 0.55,  8,  8 ],

	[ "VLLB-1" ,   6.20,  6.20, 0.55,  8,  6 ],
	[ "VMMB"   ,   7.00,  7.00, 0.55,  9,  9 ],
	# e = 0.65
	[ "VEEC"   ,   0.70,  0.70, 0.55,  2,  2 ],
	[ "VEEC-1" ,   1.65,  1.65, 0.40,  3,  3 ],
	[ "VEEC-2" ,   1.65,  1.65, 0.40,  2,  2 ],
	[ "VEEC-3" ,   1.65,  1.65, 0.40,  2,  2 ],
	[ "VGEC"   ,   1.70,  0.70, 0.55,  4,  2 ],
	[ "VGGC"   ,   1.70,  1.70, 0.55,  4,  4 ],
	[ "VGGC-1" ,   2.65,  2.65, 0.40,  3,  3 ],
	[ "VGGC-2" ,   2.65,  2.65, 0.40,  4,  4 ],
	[ "VGGC-3" ,   2.60,  2.60, 0.40,  4,  4 ],

	[ "VGGC-4" ,   2.40,  2.40, 0.55,  4,  4 ],
	[ "VHGC"   ,   2.70,  1.70, 0.55,  5,  4 ],
	[ "VHGC-1" ,   3.35,  2.45, 0.40,  5,  4 ],
	[ "VHHC"   ,   2.70,  2.70, 0.55,  5,  5 ],
	[ "VHHC-1" ,   3.65,  3.65, 0.40,  6,  6 ],
	[ "VHHC-2" ,   3.65,  3.65, 0.40,  5,  5 ],
	[ "VHJC"   ,   3.65,  4.65, 0.40,  5,  6 ],
	[ "VJHC"   ,   3.70,  2.70, 0.55,  6,  5 ],
	[ "VJJC"   ,   3.70,  3.70, 0.55,  7,  7 ],

	[ "VJJC-1" ,   4.65,  4.65, 0.40,  6,  6 ],
	[ "VJJC-2" ,   4.65,  4.65, 0.40,  8,  8 ],
	[ "VJJC-3" ,   4.65,  4.65, 0.40,  7,  7 ],
	[ "VJJC-4" ,   4.30,  4.30, 0.40,  7,  7 ],
	[ "VKKC"   ,   4.70,  4.70, 0.55,  8,  8 ],
	[ "VKKC-1" ,   5.65,  5.65, 0.40,  9,  9 ],
	[ "VKKC-2" ,   5.65,  5.65, 0.40,  8,  8 ],
	[ "VKMC"   ,   5.10,  7.10, 0.55,  8, 11 ], # says e = 0.50 in summary table 5B p6

	[ "VLLC"   ,   5.70,  5.70, 0.55, 10, 10 ],
	[ "VLLC-1" ,   6.65,  6.65, 0.40,  9,  9 ],
	[ "VLLC-2" ,   6.65,  6.65, 0.40, 11, 11 ],
	[ "VLLC-3" ,   6.65,  6.65, 0.40, 10, 10 ],
	[ "VLLC-4" ,   6.45,  6.45, 0.40, 11, 11 ],
	[ "VMMC"   ,   7.65,  7.65, 0.40, 12, 12 ],
	[ "VMMC-1" ,   7.65,  7.65, 0.40, 11, 11 ],
	[ "VMMC-2" ,   6.40,  6.40, 0.40, 11, 11 ],
	[ "VMMC-3" ,   7.35,  7.35, 0.40, 11, 11 ],
	# e = 0.50
	[ "VCCD"   ,   0.55,  0.55, 0.40,  2,  2 ],
	[ "VEED-1" ,   0.70,  0.70, 0.55,  3,  3 ],
	[ "VEED-2" ,   0.70,  0.70, 0.40,  4,  4 ],
	[ "VEED-3" ,   1.65,  1.65, 0.40,  3,  3 ],
	[ "VEED-4" ,   1.65,  1.65, 0.40,  4,  4 ],
	[ "VEED-5" ,   1.45,  1.45, 0.40,  3,  3 ],
	[ "VEED-6" ,   1.45,  1.45, 0.40,  4,  4 ],
	[ "VEED-7" ,   1.25,  1.25, 0.50,  4,  4 ],
	[ "VFFD"   ,   2.00,  2.00, 0.55,  5,  5 ],

	[ "VFFD-1" ,   1.70,  1.70, 0.55,  5,  5 ], # corner terminal close
	[ "VFSD"   ,   2.00,  3.00, 0.55,  4,  8 ], # corner terminal close
	[ "VFSD-1" ,   1.70,  2.70, 0.55,  4,  8 ],
	[ "VFSD-2" ,   1.85,  2.85, 0.40,  4,  8 ],
	[ "VGED"   ,   1.70,  0.70, 0.55,  5,  3 ],
	[ "VGGD-1" ,   1.70,  1.70, 0.55,  5,  5 ],
	[ "VGGD-2" ,   1.70,  1.70, 0.40,  6,  6 ],
	[ "VGGD-3" ,   2.20,  2.20, 0.55,  4,  3 ],
	[ "VGGD-4" ,   2.20,  2.20, 0.55,  4,  4 ],

	[ "VGGD-5" ,   2.65,  2.65, 0.40,  5,  5 ],
	[ "VGGD-6" ,   2.65,  2.65, 0.40,  6,  6 ],
	[ "VGGD-7" ,   2.80,  2.80, 0.40,  6,  8 ], # thiny mask between corner terminals, no silk
	[ "VGGD-8" ,   2.40,  2.40, 0.40,  6,  6 ],
	[ "VGGD-9" ,   1.75,  1.75, 0.50,  6,  6 ],
	[ "VGGD-10",   2.35,  2.35, 0.40,  4,  4 ],
	[ "VGGD-11",   2.35,  2.35, 0.40,  5,  5 ],
	[ "VGHD"   ,   1.70,  2.70, 0.40,  6,  8 ],
	[ "VGHD-1" ,   2.65,  3.65, 0.40,  5,  7 ],
	[ "VGHD-2" ,   2.80,  3.80, 0.40,  6,  6 ],

	[ "VGHD-3" ,   2.65,  3.65, 0.40,  6,  8 ],
	[ "VSTD"   ,   3.00,  4.00, 0.55,  6, 10 ],
	[ "VSTD-1" ,   2.70,  3.70, 0.55,  6, 10 ],
	[ "VSUD"   ,   3.00,  5.00, 0.55,  6, 12 ],
	[ "VSUD-1" ,   2.70,  4.70, 0.55,  6, 12 ],
	[ "VHGD"   ,   2.70,  1.70, 0.55,  7,  5 ],
	[ "VHHD-1" ,   2.70,  2.70, 0.55,  7,  7 ],
	[ "VHHD-2" ,   2.70,  2.70, 0.40,  8,  8 ],
	[ "VHHD-3" ,   3.65,  3.65, 0.40,  7,  7 ],
	[ "VHHD-4" ,   3.65,  3.65, 0.40,  8,  8 ],

	[ "VHHD-5" ,   3.45,  3.45, 0.40,  8,  8 ],
	[ "VHHD-6" ,   2.15,  2.15, 0.50,  8,  8 ],
	[ "VHJD"   ,   3.20,  4.20, 0.55,  7,  9 ],
	[ "VHKD"   ,   2.70,  4.70, 0.40,  7, 12 ],
	[ "VHKD-1" ,   3.65,  5.65, 0.40,  7, 12 ],
	[ "VHKD-2" ,   3.30,  5.30, 0.40,  8, 12 ],
	[ "VTUD"   ,   4.00,  5.00, 0.55,  8, 12 ],
	[ "VTUD-1" ,   3.70,  4.70, 0.55,  8, 12 ],
	[ "VJHD"   ,   3.70,  2.70, 0.55,  9,  7 ],

	[ "VJJD-1" ,   3.70,  3.70, 0.55,  9,  9 ],
	[ "VJJD-2" ,   3.70,  3.70, 0.40, 10, 10 ],
	[ "VJJD-3" ,   4.20,  4.20, 0.55, 10,  9 ],
	[ "VJJD-4" ,   4.65,  4.65, 0.40,  9,  9 ],
	[ "VJJD-5" ,   4.65,  4.65, 0.40, 10, 10 ],
	[ "VJJD-6" ,   2.75,  2.75, 0.50, 10, 10 ],
	[ "VJJD-7" ,   4.20,  4.20, 0.55,  8,  8 ],
	[ "VJJD-8" ,   4.20,  4.20, 0.40,  9,  9 ],
	[ "VKHD"   ,   3.75,  2.25, 0.40, 12,  7 ],

	[ "VKKD"   ,   5.65,  5.65, 0.40, 10, 10 ],
	[ "VKKD-1" ,   4.70,  4.70, 0.55, 11, 11 ],
	[ "VKKD-2" ,   4.70,  4.70, 0.40, 12, 12 ],
	[ "VKKD-3" ,   5.65,  5.65, 0.40, 11, 11 ],
	[ "VKKD-4" ,   5.65,  5.65, 0.40, 12, 12 ],
	[ "VKKD-5" ,   4.40,  4.40, 0.55, 12, 10 ],
	[ "VKKD-6" ,   3.35,  3.35, 0.50, 12, 12 ],
	[ "VKKD-7" ,   4.40,  4.40, 0.55, 10, 12 ],
	[ "VKKD-8" ,   5.10,  5.10, 0.55, 11, 13 ],

	[ "VLLD"   ,   6.65,  6.65, 0.40, 12, 12 ],
	[ "VLLD-1" ,   5.70,  5.70, 0.55, 13, 13 ],
	[ "VLLD-2" ,   5.70,  5.70, 0.40, 14, 14 ],
	[ "VLLD-3" ,   6.20,  6.20, 0.55, 13, 11 ],
	[ "VLLD-4" ,   6.65,  6.65, 0.40, 13, 13 ],
	[ "VLLD-5" ,   6.65,  6.65, 0.40, 14, 14 ],
	[ "VLLD-6" ,   4.30,  4.30, 0.50, 14, 14 ],
	[ "VMMD"   ,   7.65,  7.65, 0.40, 16, 16 ],
	[ "VMMD-1" ,   7.65,  7.65, 0.40, 15, 15 ],

	[ "VMMD-2" ,   7.65,  7.65, 0.40, 14, 14 ],
	[ "VMMD-3" ,   5.35,  5.35, 0.50, 16, 16 ], # corner terminal close
	[ "VMMD-4" ,   6.75,  6.75, 0.40, 16, 16 ],
	[ "VNND-1" ,   7.70,  7.70, 0.55, 16, 16 ],
	[ "VNND-2" ,   7.70,  7.70, 0.55, 17, 17 ],
	[ "VNND-3" ,   6.35,  6.35, 0.50, 18, 18 ], # corner terminal close
	[ "VNND-4" ,   6.00,  6.00, 0.40, 18, 18 ],
	[ "VRRD"   ,   9.70,  9.70, 0.55, 20, 20 ],
	# e = 0.40
	[ "VEEE"   ,   1.10,  1.10, 0.40,  5,  5 ],
	[ "VEEE-1" ,   1.10,  1.10, 0.40,  4,  4 ], # unclear pdf, but min/max points to L = 0.40
	[ "VGGE"   ,   2.10,  2.10, 0.40,  7,  7 ],
	[ "VHHE"   ,   3.10,  3.10, 0.40,  9,  9 ],
	[ "VHHE-1" ,   3.60,  3.60, 0.40, 10, 10 ],
	[ "VJJE"   ,   4.10,  4.10, 0.40, 12, 12 ],
	[ "VJJE-1" ,   4.60,  4.60, 0.40, 12, 12 ],
	[ "VGHE"   ,   2.50,  3.50, 0.40,  7,  9 ],
	[ "VGHE-1" ,   2.50,  3.50, 0.40,  7, 10 ],

	[ "VLLE-1" ,   6.10,  6.10, 0.40, 17, 17 ],
	[ "VLLE-2" ,   6.45,  6.45, 0.40, 16, 16 ],
	[ "VMME"   ,   7.10,  7.10, 0.40, 18, 18 ],
	[ "VMME-1" ,   7.10,  7.10, 0.40, 19, 19 ],
	[ "VNNE"   ,   8.10,  8.10, 0.40, 22, 22 ],
	[ "VNNE-1" ,   6.75,  6.75, 0.40, 22, 22 ],
	[ "VKKE"   ,   5.10,  5.10, 0.40, 14, 14 ],
	[ "VLLE"   ,   6.10,  6.10, 0.40, 16, 16 ],

	[ "VRRE"   ,  10.10, 10.10, 0.40, 25, 25 ],
	[ "VRRE-1" ,   6.75,  6.75, 0.40, 25, 25 ],
	[ "VRRE-2" ,  10.10, 10.10, 0.40, 27, 27 ],
    );

    #or my $r (sort { $$a[0] cmp $$b[0] } @data) {
    for my $r (@data) {
	my ($var, $D2, $E2, $L, $ND, $NE ) = @$r;
	my @V = split(//, $var);
	my $A = $var1{$V[0]};
	my $D = $var2{$V[1]};
	my $E = $var2{$V[2]};
	my $e = $var4{$V[3]};
	my $N = 2*($ND + $NE);
	my $b = $b{$e};

	#rintf "%5.2fx%5.2f %5.2f %3d %s\n", $D, $E,  $e, $N, $var; # to compare with table p.5

	#printf "%-7s  %5.2f %5.2f   %5.2f %5.2f %4.2f  %3d %2d %2d\n",
	#       $var,   $D,   $E,    $D2,  $E2,   $L,  $N, $ND, $NE; # to compare with table 5..

	my %ol = ( b => 0, c => 0.4, d => 0.6 ); # , x => 1.5  a => -0.2,
	for my $key (sort keys %ol) {
	    my $outer_len = $ol{$key};
	    my $pfx;

	    $pfx = "$name-${var}_${key}s";
	    pkg_smdnR($pfx, $doc, [$ND, $NE], [ $e, $b, $L, $outer_len, 0 ], [$D, $E], [$D2,$E2]);
	    $pfx = "$name-${var}_${key}r";
	    pkg_smdnR($pfx, $doc, [$ND, $NE], [ $e, $b, $L, $outer_len, 1 ], [$D, $E], [$D2,$E2]);
	    $pfx = "$name-${var}_${key}s3";
	    pkg_smdnR($pfx, $doc, [$ND, $NE], [ $e, $b, $L, $outer_len, 0 ], [$D, $E], [$D2,$E2,1.00,0.30]);
	    $pfx = "$name-${var}_${key}r3";
	    pkg_smdnR($pfx, $doc, [$ND, $NE], [ $e, $b, $L, $outer_len, 1 ], [$D, $E], [$D2,$E2,1.00,0.30]);
	    $pfx = "$name-${var}_${key}s4";
	    pkg_smdnR($pfx, $doc, [$ND, $NE], [ $e, $b, $L, $outer_len, 0 ], [$D, $E], [$D2,$E2,1.00,0.40]);
	    $pfx = "$name-${var}_${key}r4";
	    pkg_smdnR($pfx, $doc, [$ND, $NE], [ $e, $b, $L, $outer_len, 1 ], [$D, $E], [$D2,$E2,1.00,0.40]);
	}

    }
}
#gen_jedec_mo220();

sub gen_jedec_mo223() {
    my $name = "jedec_mo-223";
    # plastic thin shrink small outline package (shrink sot)
    my $doc  = "# http://www.jedec.org/  MO-223A.pdf\n";
    my $D1 = undef;
    my $E2 = undef;
    my $h = undef;
    # common dim. table, p3
    my  (  $A,  $A1,  $A2,  $A3,   $c,  $c1,  $D,   $E,   $E1,  $L,   $L1,  $L2,  $R,   $R1) =
	(1.10, 0.10, 0.90, 0.25, 0.17, 0.13, 2.00, 2.10, 1.25, 0.30, 0.42, 0.25, 0.10, 0.17);
    my @data = (
	# $var,  $b,   $b1,  $e,   $e1, $N
	[ "AA", 0.23, 0.20, 0.65, 1.30, 6, ],
	[ "AB", 0.23, 0.20, 0.65, 1.30, 6, undef, [ 1..4, undef, 5 ] ], # note 6, pin at pos.5 removed
	[ "BA", 0.22, 0.20, 0.50, 1.50, 8, ],
    );

    for my $r (@data) {
	my ($var,  $b,   $b1,  $e,   $e1, $N, $rname, $rnum) = @$r;
	my $pfx = $name . "-" . $var;
	pkg_smdpinsR($pfx, $doc, [$N/2, 0], [$e, $b, $L], [$D, $E1, 0, 0], [$D,$E], undef, $rnum);
    }
}
#gen_jedec_mo223();

sub gen_jedec_mo241() {
    my $name = "jedec_mo-241";
    # dual comapatible thermally enhanced
    # plastic very thin and very very thin
    # fine pitch quad flat no lead package families
    # HW-PQFP HV-PQFP PSO-N
    my $doc  = "# http://www.jedec.org/  MO-241B.pdf\n" .
	"# Note: D2/E2 are maximum values, k is minimum\n" .
	"#   soo don't use theese, use your components actual values\n";

    # common dim. table 1, p2
    my  (  $A,  $A1,  $A3,   $b,  $L1,  $k,  $R) =
	(0.90, 0.02, 0.20, 0.25, 0.07, 0.20, 0.13);
    my @data = (
	# table 3, p3
	#  $var,    $D,   $E,  $D2,  $E2,  $e, $e1,  $L, $N, $ND, $NE
	[ "VAA",  3.00, 2.50, 1.65, 1.15, 0.5, 0.5, 0.4, 14,   5,   2 ],
	[ "VAB",  3.50, 2.50, 2.15, 1.15, 0.5, 0.5, 0.4, 16,   6,   2 ],
	[ "VAC",  4.50, 2.50, 3.15, 1.15, 0.5, 0.5, 0.4, 20,   8,   2 ],
	[ "VBA",  3.50, 3.50, 2.15, 2.15, 0.5, 1.5, 0.4, 14,   5,   2 ],
	[ "VBB",  4.00, 3.50, 2.65, 2.15, 0.5, 1.5, 0.4, 16,   6,   2 ],
	[ "VBC",  4.50, 3.50, 3.15, 2.15, 0.5, 1.5, 0.4, 20,   8,   2 ],
    );

    for my $r (@data) {
	my ($var,    $D,   $E,  $D2,  $E2,  $e, $e1,  $L, $N, $ND, $NE ) = @$r;
	my $pfx = $name . "-" . $var;
	#pkg_smdnm($pfx, $doc, [$ND, $NE], [$e, $b, $L], [$D, $E, 0,0], [$D2, $E2], [$N, 1..$N-1]);
	pkg_smdnRm($pfx, $doc, [$ND, $NE], [$e, $b, $L], [$D, $E, 0,0], [$D2, $E2], [2..$N, 1]);
    }

    $name = "nexperia";
    $doc = "# http://www.farnell.com/datasheets/3163649.pdf\n";
    @data = (
	[ "DHVQFN20",  4.50, 2.50, 3.00, 1.00, 0.5, 0.5, 0.4, 20,   8,   2 ], # based on VAC above
    );
    for my $r (@data) {
	my ($var,    $D,   $E,  $D2,  $E2,  $e, $e1,  $L, $N, $ND, $NE ) = @$r;
	my $pfx = $name . "_" . $var;
	#pkg_smdnm($pfx, $doc, [$ND, $NE], [$e, $b, $L], [$D, $E, 0,0], [$D2, $E2], [$N, 1..$N-1]);
	pkg_smdnRm($pfx, $doc, [$ND, $NE], [$e, $b, $L], [$D, $E, 0,0], [$D2, $E2], [2..$N, 1]);
    }


}
#gen_jedec_mo241();

sub gen_jedec_mo259() {
    my $name = "jedec_mo-259";
    # very very thin small outline package family, type I
    my $doc  = "# http://www.jedec.org/  MO-142D.pdf\n";
    my (    $A,  $A1,  $A2,   $b,  $b1,   $c,  $c1,    $e,   $L,  $L1, ) =
	( 0.70, 0.05, 0.58, 0.22, 0.20, 0.14, 0.127, 0.50, 0.50, 0.25, );

    my @data = (
	#  var      D     D1      E     N
	[ "AA"  , 17.00, 15.40, 12.00, 48, ],
    );
    my $h = undef;
    my $E1 = undef;
    my $E2 = undef;

    for my $r (@data) {
	my ($var, $D, $D1, $E, $N, ) = @$r;
	my $pfx = $name . "-" . $var;
	pkg_smdpins($pfx, $doc, [0, $N/2], [$e, $b, $L], [$D1, $E], [$D,$E]);
    }
}
#gen_jedec_mo259();

sub gen_jedec_mo271() {
    my $name = "jedec_mo-271";
    # exposed pad plastic small outline family, 7.60mm body width
    my $doc  = "# http://www.jedec.org/  MO-271A.pdf\n";
    # Thermal bottom pad with dimensions D1 and E2 have wide margins, I use max values, check manufakturer
    my (   $A,   $A1,  $A2,  $c,   $c1,   $D,    $E,   $E1,  $L,   $L1,  $L2,  $R,   $R1,  $h,) =
	( 2.45, 0.05, 0.10, 0.27, 0.25, 10.30, 10.40, 7.60, 0.70, 1.40, 0.25, 0.07, 0.07, 0.32);


    my @data = (
	# $var,  $b,   $b1,  $D1,  $E2,  $e,  $N
	[ "AA", 0.41, 0.37, 7.50, 5.00, 1.00, 20, ],
	[ "AB", 0.41, 0.37, 5.50, 5.00, 1.00, 20, ],
	[ "BA", 0.40, 0.40, 7.50, 5.00, 0.80, 24, ],
	[ "BB", 0.40, 0.40, 5.50, 5.00, 0.80, 24, ],
	[ "CA", 0.33, 0.30, 7.50, 5.00, 0.65, 28, ],
	[ "CB", 0.33, 0.30, 5.50, 5.00, 0.65, 28, ],
	[ "DA", 0.25, 0.25, 7.50, 5.00, 0.50, 36, ],
	[ "DB", 0.25, 0.25, 5.50, 5.00, 0.50, 36, ],
    );

    for my $r (@data) {
	my ($var,  $b,   $b1,  $D1,  $E2,  $e,  $N) = @$r;
	my $pfx = $name . "-" . $var;
	pkg_smdpinsR($pfx, $doc, [$N/2, 0], [$e, $b, $L], [$D, $E1], [$D,$E], [$D1, $E2, 1]);
    }
}
#gen_jedec_mo271();

sub gen_jedec_mo272() {
    my $name = "jedec_mo-272";
    # low profile, exposed pad plastic small outline family 3.90mm body width
    my $doc  = "# http://www.jedec.org/  MO-271A.pdf\n";
    # Thermal bottom pad with dimensions D1 and E2 have wide margins, I use max values, check manufakturer
    my (   $A,   $A1,  $A2,  $c,   $c1,   $D,    $E,   $E1,  $L,   $L1,  $L2,  $R,   $R1,  $h,) =
	( 1.70, 0.05, 1.35, 0.21, 0.20,  4.90,  6.00, 3.90, 0.60, 1.00, 0.25, 0.07, 0.07, 0.25);
    $h = undef; # too small to be clearly visible

    my @data = (
	# $var,  $b,   $b1,  $D1,  $E2,  $e,  $N
	[ "AA", 0.41, 0.40, 4.00, 3.00, 1.00, 10, ],
	[ "BA", 0.40, 0.40, 4.00, 3.00, 0.80, 12, ],
	[ "CA", 0.33, 0.30, 4.00, 3.00, 0.65, 14, ],
	[ "DA", 0.25, 0.25, 4.00, 3.00, 0.50, 16, ],
    );

    for my $r (@data) {
	my ($var,  $b,   $b1,  $D1,  $E2,  $e,  $N ) = @$r;
	my $pfx = $name . "-" . $var;
	pkg_smdpinsR($pfx, $doc, [$N/2, 0], [$e, $b, $L], [$D, $E1], [$D,$E], [$D1, $E2, 1]);
    }
}
#gen_jedec_mo272();

sub gen_jedec_mo286() {
    my $name = "jedec_mo-286";
    # plastic small outline, wide body soic, 7.5 body width, 0.65 pitch
    my $doc  = "# http://www.jedec.org/  MO-265B.pdf\n";
    # Thermal bottom pad with dimensions D1 and E2 have wide margins, I use max values, check manufakturer
    my (   $A2,   $b,  $b1,    $c,   $c1,    $E,  $E1,   $e,   $L,  $L1,   $h,) =
	( 2.35, 0.32, 0.29,  0.24,  0.21, 10.30, 7.50, 0.65, 0.70, 1.40, 0.50,);
    $h = undef; # too small to be clearly visible

    my @data = (
	# $var,  $N,   $A,  $A1,    $D,   $D1,   $E2,
	[ "AA",  32, 2.80, 0.20, 11.00, undef, undef, ],
	[ "AB",  54, 2.80, 0.20, 17.90, undef, undef, ],
	[ "AC",  36, 2.65, 0.15, 12.80, undef, undef, ],
	[ "AD",  52, 2.65, 0.15, 17.90, undef, undef, ],
	[ "BA",  32, 2.65, 0.08, 11.00,  2.50,  2.50, ],
	[ "BB",  54, 2.65, 0.08, 17.90,  2.50,  2.50, ],
	[ "BC",  36, 2.55, 0.05, 12.80,  2.50,  2.50, ],
	[ "CA",  32, 2.65, 0.08, 11.00,  2.50,  2.50, ],
	[ "CB",  54, 2.65, 0.08, 17.90,  2.50,  2.50, ],
    );

    for my $r (@data) {
	my ($var,  $N,   $A,  $A1,    $D,   $D1,   $E2, ) = @$r;
	my $pfx = $name . "-" . $var;
	pkg_smdpinsR($pfx, $doc, [$N/2, 0], [$e, $b, $L], [$D, $E1], [$D,$E], [$D1, $E2, 1]);
    }
}
#gen_jedec_mo286();

sub gen_jedec_ms012() {
    my $name = "jedec_ms-012";
    # plastic small outline, 1.27mm pitch, 3.90m body width
    my $doc  = "# http://www.jedec.org/  MS-012F.pdf\n";
    # Thermal bottom pad with dimensions D1 and E2 have wide margins, I use max values, check manufakturer
    my (   $A2,   $b,  $b1,    $c,   $c1,    $E,  $E1,   $e,   $L,  $L1,   $h,) =
	( 1.25, 0.41, 0.38,  0.18,  0.16,  6.00, 3.90, 1.27, 0.85, 1.04, 0.38,);
    $h = undef; # too small to be clearly visible

    my @data = (
	# $var,  $A,   $A1,    $D,   $D1,   $E2, $N
	[ "AA", 1.75, 0.17,  4.90, undef, undef,  8 ],
	[ "AB", 1.75, 0.17,  8.65, undef, undef, 14 ],
	[ "AC", 1.75, 0.17,  9.90, undef, undef, 16 ],
	[ "BA", 1.70, 0.07,  4.90,  1.50,  1.00,  8 ],
	[ "BB", 1.70, 0.07,  8.65,  1.50,  1.00, 14 ],
	[ "BC", 1.70, 0.07,  9.90,  1.50,  1.00, 16 ],
    );

    for my $r (@data) {
	my ($var, $A, $A1, $D, $D1, $E2, $N ) = @$r;
	my $pfx = $name . "-" . $var;
	pkg_smdpinsR($pfx, $doc, [$N/2, 0], [$e, $b, $L], [$D, $E1], [$D,$E], [$D1, $E2, 1]);
    }
}
#gen_jedec_ms012();

sub gen_jedec_ms013() {
    my $name = "jedec_ms-013";
    # very thick profile, plastic small outline family, 1.27 mm pitch, 7.50 mm body width
    my $doc  = "# http://www.jedec.org/  MS-013F.pdf\n";
    # Thermal bottom pad with dimensions D1 and E2 are only specified with a min value, check manufakturer
    # I'll use the mean of body and this minimum
    my  (  $A2,   $b,  $b1,    $c,   $c1,    $E,  $E1,   $e,   $L,  $L1,  $L2,   $R,   $h, ) =
	( 2.05, 0.41, 0.38,  0.21,  0.20, 10.30, 7.50, 1.27, 0.85, 1.40, 0.25, 0.07, 0.50, );

    my @data = (
	# $var,  $A,   $A1,    $D,   $D1,   $E2, $N
	[ "AA", 2.65, 0.20, 10.30, undef, undef, 16 ],
	[ "AB", 2.65, 0.20, 11.55, undef, undef, 18 ],
	[ "AC", 2.65, 0.20, 12.80, undef, undef, 20 ],
	[ "AD", 2.65, 0.20, 15.40, undef, undef, 24 ],
	[ "AE", 2.65, 0.20, 17.90, undef, undef, 28 ],
	[ "AF", 2.65, 0.20,  9.00, undef, undef, 14 ],

	[ "BA", 2.50, 0.07, 10.30,  2.00,  3.00, 16 ],
	[ "BB", 2.50, 0.07, 11.55,  2.00,  3.00, 18 ],
	[ "BC", 2.50, 0.07, 12.80,  2.00,  3.00, 20 ],
	[ "BD", 2.50, 0.07, 15.40,  2.00,  3.00, 24 ],
	[ "BE", 2.50, 0.07, 17.90,  2.00,  3.00, 28 ],
	[ "BF", 2.50, 0.07,  9.00,  2.00,  3.00, 14 ],
    );

    for my $r (@data) {
	my ($var, $A, $A1, $D, $D1, $E2, $N ) = @$r;
	my $pfx = $name . "-" . $var;
	if (defined($D1)) {
	    $D1 = ($D1 + $D )/2;
	    $E2 = ($E2 + $E1)/2;
	}
	pkg_smdpinsR($pfx, $doc, [$N/2, 0], [$e, $b, $L], [$D, $E1, 0, 0], [$D,$E], [$D1, $E2]);
    }
}
#gen_jedec_ms013();

sub gen_jedec_ms026() {
    my $name = "jedec_ms-026";
    # low/thin profile plastic quad flat package, 2.00 footprint optional heat slug
    my $doc  = "# http://www.jedec.org/  MS-026D.pdf\n";

    my  (   $c,  $c1,  $D2,  $E2,   $L,  $L1,  $R1,  $R2,   $S) =
	( 0.16, 0.12, 2.00, 2.00, 0.60, 1.00, 0.08, 0.14, 0.20);

    my %A2 = ( # $A1 => [ $A, $A1 ],
	1.00 => [ 1.20, 0.10 ], # variation Axx
	1.40 => [ 1.60, 0.10 ], # variation Bxx
    );
    # $D = $D1 + 2.00, dito $E = $E1 + 2.00
    my %pin = ( # $e => [ $b, $b1 ]
	0.40 => [ 0.18, 0.16 ],
	0.50 => [ 0.22, 0.20 ],
	0.65 => [ 0.32, 0.30 ],
	0.80 => [ 0.37, 0.35 ],
	1.00 => [ 0.42, 0.40 ],
    );

    my @data = (
	#  $var  $D1 $E1  $e,  Nx  Ny
	[ "xKA",  4,  4, 0.65,  20 ],
	[ "xKB",  4,  4, 0.50,  24 ],
	[ "xKC",  4,  4, 0.40,  32 ],

	[ "xAA",  5,  5, 0.50,  32 ],
	[ "xAB",  5,  5, 0.40,  40 ],

	[ "xBA",  7,  7, 0.80,  32 ],
	[ "xBB",  7,  7, 0.65,  40 ],
	[ "xBC",  7,  7, 0.50,  48 ],
	[ "xBD",  7,  7, 0.40,  64 ],

	[ "xCA", 10, 10, 1.00,  36 ],
	[ "xCB", 10, 10, 0.80,  44 ],
	[ "xCC", 10, 10, 0.65,  52 ],
	[ "xCD", 10, 10, 0.50,  64 ],
	[ "xCE", 10, 10, 0.40,  80 ],

	[ "xDA", 12, 12, 1.00,  44 ],
	[ "xDB", 12, 12, 0.80,  52 ],
	[ "xDC", 12, 12, 0.65,  64 ],
	[ "xDD", 12, 12, 0.50,  80 ],
	[ "xDE", 12, 12, 0.40, 100 ],

	[ "xEA", 14, 14, 1.00,  52 ],
	[ "xEB", 14, 14, 0.80,  64 ],
	[ "xEC", 14, 14, 0.65,  80 ],
	[ "xED", 14, 14, 0.50, 100 ],
	[ "xEE", 14, 14, 0.40, 120 ],

	[ "xFA", 20, 20, 0.65, 112 ],
	[ "xFB", 20, 20, 0.50, 144 ],
	[ "xFC", 20, 20, 0.40, 176 ],

	[ "xGA", 24, 24, 0.50, 176 ],
	[ "xGB", 24, 24, 0.40, 216 ],

	[ "xHA", 20, 14, 0.65, 30, 20 ],
	[ "xHB", 20, 14, 0.50, 38, 26 ],

	[ "xJA", 28, 28, 0.65, 160 ],
	[ "xJB", 28, 28, 0.50, 208 ],
	[ "xJC", 28, 28, 0.40, 258 ],
    );

    for my $r (@data) {
	my ($var, $D1, $E1, $e, $Nx, $Ny ) = @$r;
	my ($b, $b1) = @{$pin{$e}};
	#my ($A, $A1) = @{$A2{$A2}};
	my $D = $D1 + 2;
	my $E = $E1 + 2;
	my $pfx = $name . "-" . $var;
	#printf "%02dx%02d %.2f %3d %.2f %s\n", $E1, $D1,  $e, $N, $A2, $var; # to compare with table p.5
	#printf "%-4s  %.2f %.2f %.2f   %.2f %2d %.2f %2d   %3d %.2f %.2f %.2f\n",
	#        $var, $A,  $A1, $A2,   $D,  $D1, $E, $E1,  $N, $e, $b, $b1; # to compare with table p6-10

	if (!defined($Ny)) {
	    $Ny = $Nx/4;
	    $Nx = $Ny;
	}
	pkg_smdpinsR($pfx, $doc, [$Nx, $Ny], [$e, $b, $L], [$D1, $E1, 0, 0], [$D,$E]);
    }
}
#gen_jedec_ms026();

sub gen_jedec_ms029() {
    my $name = "jedec_ms-029";
    # fine pitch plastic quad flat package outline 2.6mm fooprint
    my $doc  = "# http://www.jedec.org/  Ms-029a.pdf\n";

    my  (  $R2,  $R1,   $c,  $c1,   $L,  $L1,   $S) =
	( 0.16, 0.08, 0.15, 0.12, 0.60, 1.30, 0.20);

    my %A = ( # $A => [ $A1, $A2 ],
	2.45 => [ 0.15, 2.00 ],
	2.70 => [ 0.37, 2.00 ],
	3.15 => [ 0.15, 2.70 ],
	3.40 => [ 0.37, 2.70 ],
	3.85 => [ 0.15, 3.40 ],
	4.10 => [ 0.37, 3.40 ],
	4.50 => [ 0.37, 3.80 ],
    );
    # $D = $D1 + 2.60, dito $E = $E1 + 2.60
    my %pin = ( # $e => [ $b, $b1 ]
	0.40 => [ 0.18, 0.16 ],
	0.50 => [ 0.22, 0.20 ],
    );

    my @data = (
	# $var,     $A,   $D1,   $E1,   $e,
	[ "AA"  , 2.45, 10.00, 10.00, 0.50,  64 ],
	[ "AB"  , 2.45, 10.00, 10.00, 0.40,  80 ],
	[ "BA"  , 2.45, 12.00, 12.00, 0.50,  80 ],
	[ "BB"  , 3.15, 12.00, 12.00, 0.50,  80 ],
	[ "BC"  , 2.45, 12.00, 12.00, 0.40, 100 ],
	[ "CA"  , 2.45, 14.00, 14.00, 0.50, 100 ],

	[ "CB"  , 3.15, 14.00, 14.00, 0.50, 100 ],
	[ "CC"  , 2.45, 14.00, 14.00, 0.40, 120 ],
	[ "CD"  , 3.15, 14.00, 14.00, 0.40, 120 ],
	[ "DA-1", 2.70, 20.00, 20.00, 0.50, 144 ],
	[ "DB-1", 3.40, 20.00, 20.00, 0.50, 144 ],
	[ "DC-1", 2.70, 20.00, 20.00, 0.40, 176 ],

	[ "DD-1", 3.40, 20.00, 20.00, 0.40, 176 ],
	[ "DA-2", 2.45, 20.00, 20.00, 0.50, 144 ],
	[ "DB-2", 3.15, 20.00, 20.00, 0.50, 144 ],
	[ "DC-2", 2.45, 20.00, 20.00, 0.40, 176 ],
	[ "DD-2", 3.15, 20.00, 20.00, 0.40, 176 ],
	[ "EA"  , 4.10, 24.00, 24.00, 0.50, 176 ],

	[ "EB"  , 4.10, 24.00, 24.00, 0.40, 216 ],
	[ "FA-1", 4.10, 28.00, 28.00, 0.50, 208 ],
	[ "FB-1", 4.10, 28.00, 28.00, 0.40, 256 ],
	[ "FA-2", 3.85, 28.00, 28.00, 0.50, 208 ],
	[ "FB-2", 3.85, 28.00, 28.00, 0.40, 256 ],
	[ "GA"  , 4.10, 32.00, 32.00, 0.50, 240 ],

	[ "GB"  , 4.10, 32.00, 32.00, 0.40, 296 ],
	[ "HA"  , 4.50, 36.00, 36.00, 0.50, 272 ],
	[ "HB"  , 4.50, 36.00, 36.00, 0.40, 336 ],
	[ "JA"  , 4.50, 40.00, 40.00, 0.50, 304 ],
	[ "JB"  , 4.50, 40.00, 40.00, 0.40, 376 ],
    );

    for my $r (@data) {
	my ($var, $A, $D1, $E1, $e, $N ) = @$r;
	my ($b, $b1) = @{$pin{$e}};
	my ($A1, $A2) = @{$A{$A}};
	my $D = $D1 + 2.60;
	my $E = $E1 + 2.60;
	my $pfx = $name . "-" . $var;
	#printf "%02dx%02d %.2f %3d %.2f %s\n", $E1, $D1,  $e, $N, $A2, $var; # to compare with table p.5
	#printf "%-4s  %.2f %.2f %.2f   %.2f %2d %.2f %2d   %3d %.2f %.2f %.2f\n",
	#        $var, $A,  $A1, $A2,   $D,  $D1, $E, $E1,  $N, $e, $b, $b1; # to compare with table p6-10

	pkg_smdpinsR($pfx, $doc, [$N/4, $N/4], [$e, $b, $L], [$D1, $E1, 0, 0], [$D,$E]);
    }
    {
	my ($var, $A, $D1, $E1, $e, $N ) = ( "KA"  , 3.15, 20.00, 14.00, 0.50, 128 );
	my ($b, $b1) = @{$pin{$e}};
	my ($A1, $A2) = @{$A{$A}};
	my $D = $D1 + 2.60;
	my $E = $E1 + 2.60;
	my $pfx = $name . "-" . $var;
	#printf "%02dx%02d %.2f %3d %.2f %s\n", $E1, $D1,  $e, $N, $A2, $var; # to compare with table p.5
	#printf "%-4s  %.2f %.2f %.2f   %.2f %2d %.2f %2d   %3d %.2f %.2f %.2f\n",
	#        $var, $A,  $A1, $A2,   $D,  $D1, $E, $E1,  $N, $e, $b, $b1; # to compare with table p6-10

	pkg_smdpinsR($pfx, $doc, [38, 26], [$e, $b, $L], [$D1, $E1, 0, 0], [$D,$E]);
    }
}
#gen_jedec_ms029();

sub gen_jedec_to_() {
    my $brasklapp = "# Note: this from data only, check with your component\n";

    my @data = (
	# var,   A,    b     b2    D       D1    e     e1    j      k      r      a,  N, sta, delta
	[   1, 10.41, 0.47, 0.45,  6.10,  0.00, 1.80, 0.90,     0,     0,     0,  0,  3,  90,  90 ],
	[   5,  6.35, 0.47, 0.45,  8.95,  8.13, 5.08, 2.54, 0.787, 0.775, 0.179, 45,  3,  90,  90 ],
	[   8,  7.61, 0.76,    0, 15.24, 12.30, 7.16, 3.58,     0,     0,     0,  0,  3,  90,  90 ],
	[   9,  5.70, 0.47, 0.45,  8.95,  8.17, 5.08, 2.54,     0,     0,     0,  0,  3,  90,  90 ],
	[  11,  9.50, 0.47, 0.45,  8.95,  8.17, 5.08, 2.54, 0.787, 0.775,     0, 45,  3,  90,  90 ],
	[  12,  6.35, 0.47, 0.45,  8.95,  8.13, 5.08, 2.54, 0.787, 0.775, 0.179, 45,  4,  90,  90 ],
	[  16,  5.80, 0.47,    0,  8.95,  8.13, 5.08, 2.54,     0,     0,     0,  0,  3,  90,  90 ],
	[  17,  5.00, 0.47, 0.45,  5.08,  4.08, 1.80, 0.91, 0.920, 0.970,     0, 45,  4,  90,  90 ],
	[  18,  4.80, 0.47, 0.45,  5.57,  4.74, 2.58, 1.27, 1.150, 0.970,     0, 45,  3,  90,  90 ],
	[  23,  4.57, 0.33,    0,  3.56,  2.92, 1.32, 0.66,     0,     0,     0,  0,  3,-120, 120 ],
	[  24, 11.40, 0.46,    0,  5.32,  4.32, 1.79, 0.89,     0,     0,     0,  0,  3,-120, 120 ],
	[  25, 11.94, 0.51,    0,  8.38,  7.11, 3.96, 1.98,     0,     0,     0,  0,  3,-120, 120 ],
	[  26, 12.50, 0.45,    0,  9.32,  7.63, 5.08, 2.54,     0,     0,     0,  0,  3,  90,  90 ],
	[  28,  4.81, 0.47, 0.45,  5.57,  4.74, 2.54, 1.27, 1.150, 0.970,     0, 45,  3,  90,  90 ],
	[  29,  5.84, 0.47, 0.45,  8.95,  8.13, 5.08, 2.54, 0.787, 0.775,     0, 45,  3,  90,  90 ],
	[  30, 10.20, 0.50,    0,  5.33,  4.31, 1.91, 0.95,     0,     0,     0,  0,  3,  00,  90 ], # lead dia not specified
	[  31,  9.55, 0.53, 0.45,  9.28,  7.60, 5.08, 2.54,     0,     0,     0,  0,  3,  90,  90 ],
	[  33,  6.35, 0.47, 0.45,  8.95,  8.13, 5.08, 2.54, 0.787, 0.775,     0, 45,  4,  90,  90 ],
	[  39,  6.35, 0.47, 0.45,  9.15,  8.25, 5.08, 2.54, 0.787, 0.770,     0, 45,  3,  90,  90 ],
	[  42,  5.82, 0.47, 0.45,  8.40,  7.94, 5.08, 2.54, 0.790, 0.750,     0, 45,  3,  90,  90 ],
	# and a lot more
	[  99,  4.44, 0.47, 0.45,  8.95,  8.17, 5.08, 2.54, 0.787, 0.775,     0, 45,  8,  90,  45 ],
    );

    for my $r (@data) {
	my ( $var, $A, $b, $b2, $D, $D1, $e, $e1, $j, $k, $r, $a, $N, $sta, $delta) = @$r;
	my $doc = sprintf "%s# http://www.jedec.org/  to-%03d.pdf\n", $brasklapp, $var;
	my $name = sprintf "jedec_TO-%03d", $var;
	my $lead_dia = $b;
	my $drill = lead_to_drill($lead_dia);
	my @thickness = drill2thickness($drill);

	my $dta = deg_rad($delta);
	my $spacing = 2 * $e1 * sin( $dta/2 );
	#print "spacing $spacing, delta $delta, dta $dta\n";

	for (my $ix = 0; $ix < @thickness; $ix++) {
	    my $file = sprintf("%s_%s.fp", $name, thickness_suffix($ix));
	    my $limit_radius = $thickness[$ix]/2 + $mask_gap;
	    if ($spacing/2 < $limit_radius) {
		#warn "$file: too close spacing <$spacing $limit_radius";
		next;
	    }

	    my $ang = deg_rad($sta);
	    element_start($file, $doc);
	    for (my $nx = 0 ; $nx < $N; $nx++, $ang += $dta) {
		my ($xc, $yc) = @{polar_vec( [ $e1, $ang ] )};
		#print "$xc, $yc\n";
		pin(  $xc, $yc, $drill, $thickness[$ix]);
	    }

	    if ($k) { # make a tab
		silk_circle_tab($origin, $D/2, $k, $j, $a);
	    } else {
		silk_circle($origin, $D/2, 0, 360);
	    }
	    if ($D1) {
		silk_width(0.18);
		silk_circle($origin, $D1/2, 0, 360);
		silk_width();
	    }
	    element_stop();
	}
    }
}
#gen_jedec_to_();

sub gen_nxp_sod80c() {
    my $name = "nxp_sod80c";
    my $doc = "# http://www.farnell.com/datasheets/1499163.pdf\n";
    my $body = [3.5,1.6];

    my @data = (
	# suffix, $cx, $cy, $px, $py
	[ "reflow", (4.3+2.3)/4, 0, (4.3-2.3)/2, 1.7 ],
	[ "wave"  , (4.9+2.7)/4, 0, (4.9-2.7)/2, 1.7 ],
	[ "hand"  , (6.0+2.5)/4, 0, (6.0-2.5)/2, 1.8 ], # not in the pdf above
    );

    for my $ref (@data) {
	my ($suffix, $cx, $cy, $px, $py) = @$ref;
	element_start("${name}_$suffix.fp", $doc);
	pad(-$cx, $cy, $px, $py);
	pad( $cx, $cy, $px, $py);
	pr("# body\n");
	silk_width(0.18);
	my @bbw = bb_sort(@bounding_box);
	@bbw = bb_enlarge($silk_w/2,@bbw);
	silk_crect($origin, $body, 0, \@bbw);
	bb_left_hat($bbw[0]);
	silk_width();
	element_stop();
    }
}
#gen_nxp_sod80c();

sub gen_nxp_sot158_1() {
    my $name = "nxp_sot158_1";
    my $doc = "# https://www.nxp.com/docs/en/data-sheet/PCF8566.pdf p.38/48\n";
    my $N = 40;

    my  ( $A, $A1,  $A2,  $A3,  $bp,   $c,   $D,  $E,    $e,  $HE,   $L, $Lp,  $Q,  $v,  $w,  $y,  $Z) =
	(2.7, 0.2, 2.35, 0.25, 0.36, 0.18, 15.4, 7.6, 0.762, 12.2, 2.25, 1.6, 1.1, 0.2, 0.1, 0.1, 0.5);

    pkg_smdpinsR($name, $doc, [$N/2, 0], [$e, $bp, $Lp], [$D, $E], [$D,$HE]);
}
#gen_nxp_sot158_1();

sub gen_xtl_murata() {
    my $name = "murata_";
    my $doc = "# murata.com p79e.pdf\n";

    $mask_gap = 0.07;
    my @data = (
	#  name        px      py   ds     dy     notch size
	# p.5-6,9
	[ "MCR1210"  , 1.2, 1.0, 0.495, 0.40, 0.21, 0.25 ],
	[ "MCR1612"  , 1.6, 1.2, 0.70 , 0.60, 0.30, 0.20 ],
	[ "HCR2016"  , 2.0, 1.6, 0.75 , 0.70, 0.60, 0.30 ],
	[ "HCR2520"  , 2.5, 2.0, 1.35-0.4/2, 2.20, 0.40, undef ],
	[ "TSS-5032A", 5.0, 3.2, 1.50 , 1.20, 3.90-1.5, 2.40-1.2 ],
	[ "TAS-5032F", 5.0, 3.2, 1.50 , 1.20, 3.90-1.5, 2.40-1.2 ],
	# p.17-18
	[ "TTS14"    , 5.0, 3.2, (5.6-2.4)/2, (3.8-1.2)/2, 2.4, 1.2, 0.5 ],
    );

    for my $r (@data) {
	my ($pkg, $bx, $by, $px, $py, $dx, $dy, $ns) = @$r;

	my $file = "$name$pkg.fp";
	element_start($file, $doc);
	if (defined($dy)) {
	    # four terminals
	    my $cx = ($dx + $px)/2;
	    my $cy = ($dy + $py)/2;
	    pad( -$cx,  $cy, $px, $py);
	    pad(  $cx,  $cy, $px, $py);
	    pad(  $cx, -$cy, $px, $py);
	    pad( -$cx, -$cy, $px, $py);
	} else {
	    # two terminals
	    my $cx = $dx + $px;
	    pad( -$cx,  0, $px, $py);
	    pad(  $cx,  0, $px, $py);
	}

	pr("# body\n");
	silk_width(0.18);
	my @bbw = bb_sort(@bounding_box);
	@bbw = bb_enlarge($silk_w/2,@bbw);
	silk_crect($origin, [$bx, $by], 0, \@bbw);

	pr(" # Index marker\n");
	silk_width(0.18);
	my $sx = $bbx2 + $silk_w/2;
	my $sy = $bby2 + $silk_w/2;
	my $sl = $bby2/2;
	silk_start(-$sx,  $sy-$sl);
	silk_line( -$sx,  $sy);
	silk_line( -$sx+$sl, $sy);

	element_stop();
    }
    $mask_gap = $mask_gap_default;
    silk_width();
}
#gen_xtl_murata();

sub gen_tdk_induktor() {
    my $pfx = "tdk_";
    my $doc = "# https://www.farnell.com/datasheets/2724083.pdf\n";
    my @data = (
	# [ bx   by  ]   cy      px py type
	[ [ 6.0, 6.0 ], (2.3+1.9)/2, 5.1, 1.9, "VLS6045EX" ],
    );
    pkg_twoPad($pfx, $doc, "L?", @data);
}
#gen_tdk_induktor();

sub gen_laird_inductor() {
    my $pfx = "laird_";
    my $pre  = "# https://www.laird.com/sites/default/files/";
    my $post = "-series-datasheet.pdf\n";

    my $str =
# I == T is given on I col.
# if F = -, then  - D E = D E F when F != -
# A    B    C    D    E    F    G    H    I   tt type
"2.00 1.60 1.15 0.60 0.80  -   1.60 0.80 0.80  1 TYA201610
 2.50 2.00 1.15 0.80 0.80  -   2.00 0.80 0.85  1 TYA252010
 3.00 3.00 1.30 2.50 0.75 1.50 2.70 1.20 1.00  2 TYA3012
 3.00 3.00 1.65 2.50 0.80 1.40 2.70 1.50 0.80  2 TYA3015
 4.00 4.00 1.30 3.30 1.20 1.60 3.70 1.60 1.30  2 TYA4012
 4.00 4.00 2.10 3.30 1.00 2.00 3.70 1.90 1.10  2 TYA4020
 2.50 2.00 1.00 1.50 0.80 0.80 2.00 1.65 0.85  3 TYS252010L
 3.00 3.00 1.00 2.50 0.75 1.50 2.70 1.50 0.80  2 TYS3010
 3.00 3.00 1.20 2.50 0.80 1.40 2.70 1.50 0.80  2 TYS3012
 3.00 3.00 1.50 2.50 0.90 1.20 2.70 1.20 0.90  2 TYS3015
 4.00 4.00 1.20 3.30 0.95 2.00 3.70 1.90 1.10  2 TYS4012
 4.00 4.00 1.80 3.30 0.95 2.00 3.70 1.90 1.10  2 TYS4018
 4.00 4.00 2.10 3.30 1.20 1.80 3.70 1.70 1.20  2 TYS4020
 4.00 4.00 3.00 3.30 1.00 2.00 3.70 2.00 1.00  2 TYS4030
 5.00 5.00 2.00 4.00 1.25 2.50 4.20 2.30 1.40  2 TYS5020
 5.00 5.00 4.00 1.50 2.10 -    4.20 2.30 1.40  2 TYS5040
 6.00 6.00 2.00 4.90 1.60 2.80 5.70 2.80 1.70  2 TYS6020
 6.00 6.00 2.80 4.90 1.80 2.55 5.70 2.60 1.80  2 TYS6028
 8.00 8.00 4.00 6.30 2.00 4.00 7.50 3.80 2.20  2 TYS8040
";

    my @line = split(/\n/, $str);
    my @data = ();
    for my $line (@line) {
	my ($A, $B, $C, $D, $E, $F, $G, $H, $I, $tt, $type) = split(" ", $line);
	my $doc  = $pre . lc($type) . $post;
	my $cc;

	my ($bx, $by);
	my ($cx, $cy) = (0, 0);
	my ($px, $py) = ($G, $I);
	if ($tt == 1) {
	    ($bx, $by) = ($B, $A); # A and B are reversed
	    $cy = ($H + $I)/2;
	} elsif ($tt == 2) {
	    ($bx, $by) = ($A, $B);
	    $cy = ($H + $I)/2;
	} elsif ($tt == 3) {
	    ($bx, $by) = ($B, $A); # A and B are reversed
	    $cy = $H/2;
	    #$H = $H - $I;
	} else {
	}
	push @data, [ [ $bx, $by, 0, 0.18 ], $cy, $px, $py, $type, $doc ];
    }
    pkg_twoPad($pfx, undef, "L?", @data);
}
#gen_laird_inductor();

sub gen_murata_inductor() {
    my $name = "murata_";
    my $doc = "# murata.com o05e.pdf Jan.25,2019\n";

    # p. 8, 154, and 182 part numbering
    my %size_code = ( # nominal dimensions in mm
	"02" => [ 0.4, 0.2  ],
	"03" => [ 0.6, 0.3  ],
	"04" => [ 0.8, 0.4  ],
	"15" => [ 1.0, 0.5  ],
	"18" => [ 1.6, 0.8  ],
	"21" => [ 2.0, 1.25 ],
	"2B" => [ 2.0, 1.5  ],
	"2H" => [ 2.5, 2.0  ],
	"2M" => [ 2.0, 1.6  ],
	"2U" => [ 2.5, 2.0  ],
	"31" => [ 3.2, 1.6  ],
	"32" => [ 3.2, 2.5  ],
	"3N" => [ 3.0, 3.0  ],
	"43" => [ 4.5, 3.2  ],
	"44" => [ 4.0, 4.0  ],
	"55" => [ 5.7, 5.0  ],
	"5B" => [ 5.0, 5.0  ],
	"66" => [ 6.3, 6.3  ],
    );

    # a = dist between pads, b = dist. pad end to pad end, c = pad width
    # theese are the rf inductors
    my $str = "
#Part Number     a          b      c    d

# p.138
LQM18Ff/18P	0.7      2.2-2.6  0.7
LQM18Fr/18P	0.7      1.8-2.0  0.7
LQM21D/21F/21P  1.2      3.0-4.0  1.0
LQM2MP          0.8      2.4      1.8
LQM2HP          1.6      3.0      1.5
LQM31P          2.0      4.2-5.2  1.2
LQM32P          1.9      3.6      2.7
LQH2M           0.8      2.6      1.0
LQH31C          1.0      4.5      1.5
LQH32P          1.3      3.8      2.0
LQH44P_P0       1.3      4.4      3.0   1.55
LQH44P_J0/GR    1.5      4.4      2.7   1.45
LQH5BP          1.8      5.5      4.1   1.85
LQH55D/66S      2.0      8.0      3.5    3.0
LQW15CN_00      0.4      1.4      0.6
LQW15C_10/LQW15DN 0.4    1.4      0.66
LQW18C          0.7      2.2      1.0

# p.265
LQG15H		0.4      1.4-1.5  0.5-0.6
LQG18H		0.6-0.8  1.8-2.2  0.6-0.8
LQP02TN		0.16-0.2 0.4-0.56 0.2-0.23
LQP02HQ/TQ	0.2      0.56     0.16
LQP03HQ         0.3      0.9      0.25-0.3
LQP03TN/TG/PN	0.2-0.3  0.8-0.9  0.2-0.3
LQP03TQ         0.3      0.9      0.24
LQP15M          0.4      1.4-1.5  0.5-0.6
LQP18M          0.7-0.9  1.8-2.2  0.6-0.8
LQW03A          0.23     0.65     0.4
LQW04A          0.4      1.0      0.4
LQW15A_00/10    0.5      1.2      0.65
LQW15AN_80      0.6      1.42     0.66
LQW15AW_80      0.51     1.23     0.66
LQW15CN_00      0.4      1.4      0.6
LQW15CN_10      0.4      1.4      0.66
LQW18AN_00/10/AS_00  0.6-0.8  1.9-2.0  0.7-1.0
LQW18AN_80      0.86     2.0      1.15
LQW18AS_0C      0.65     2.0      1.0
LQW18C          0.7      2.2      1.0
LQW21H          1.0      2.6      1.2
LQW2BH          0.8      3.0      1.2
LQW2BA          0.76     2.8      1.78
LQW2UA          1.27     3.3      2.54
LQH31H/LQW31H   1.0      4.5      1.5
";

    silk_width(0.18);
    my %part = ();
    my @data = map { [ split ] } grep { m/^L/; } split(/\n/, $str);
    my %ext = ("" => 0, b => 0.5, c => 1.0);
    for my $r (@data) {
	my ($part, $a, $b, $c) = @$r;
	# use the 1st family, adn max values
	$part =~ s|/.*$||;
	$a =~ s|.*-||;
	$b =~ s|.*-||;
	$c =~ s|.*-||;
	if (defined($part{$part})) {
	    next;
	}
	$part{$part} = 1;
	# p. 182 part numbering
	$part =~ m/^LQ(.)(..)((.)(.)?)?/;
	#my $structure = $1;
	my $dimension = $2;
	#my $app = $3;
	#my $category = $4;
	#print "$part $dimension ", join("/", @{$size_code{$dimension}}), "\n";

	for my $k (sort keys %ext) {
	    my $ext = $ext{$k};
	    #print "\"$k\" => $ext\n";

	    my $px = ($b + 2*$ext - $a)/2;
	    my $py = $c;
	    my $cx = ($b + 2*$ext + $a)/4;
	    my $cy = 0;
	    if ($k) { $k = "_$k"; }
	    my $file = "${name}$part$k.fp";
	    element_start($file, $doc);
	    pad(-$cx, $cy, $px, $py);
	    pad( $cx, $cy, $px, $py);
	    pkg_body_rect($size_code{$dimension}, 1);
	    element_stop();
	}
    }
    silk_width();
}
#en_murata_inductor();

sub gen_on_footprints() {
    my $file = "on_514AB_C.fp";
    my $doc = "# SOD-923, CASE 514AB, ISSUE C\n# https/www.onsemi.com/pub/Collateral/ESD9L-D.PDF\n";

    $mask_gap = 0.07;
    silk_width(0.18);

    my ($px, $py, $cx, $cy) = ( 0.36, 0.25, (1.20 - 0.36)/2, 0);
    element_start($file, $doc);
    pad(-$cx, $cy, $px, $py);
    pad( $cx, $cy, $px, $py);
    pkg_body_rect([0.80, 0.60]);
    bb_left_side($bounding_box[0]);
    element_stop();

    $mask_gap = $mask_gap_default;
    silk_width();
}
#gen_on_footprints();

sub gen_bourns_SRN() {
    my $name = "bourns";
    my @data = (
	# name,          bx,    by,  tx ,  px, sep,   py
	# semi shielded typed
	[ "SRN1060"  , 9.80, 10.00,  $u , 3.5, 3.1, 10.2 ],
	[ "SRN2009T" , 2.00,  1.60, 2.30,  $u, 0.7,  1.7 ],
	[ "SRN2010"  , 2.00,  1.60, 2.40,  $u, 0.8,  1.8 ],
	[ "SRN2010TA", 2.00,  1.60, 2.30,  $u, 0.7,  1.7 ],
	[ "SRN2012"  , 2.00,  1.60, 2.40,  $u, 0.8,  1.8 ],
	[ "SRN2508A" , 2.50,  2.00, 2.70,  $u, 0.8,  2.2 ],
	[ "SRN2510"  , 2.50,  2.00, 2.90,  $u, 0.8,  2.4 ],
	[ "SRN2510F" , 2.50,  2.00, 2.90,  $u, 1.0,  2.4 ],
	[ "SRN2512"  , 2.50,  2.00, 2.90,  $u, 0.8,  2.4 ],
	[ "SRN3010"  , 3.00,  3.00, 3.00, 0.8,  $u,  2.7 ],
	[ "SRN3010TA", 3.00,  3.00, 3.20,  $u, 1.0,  3.2 ],
	[ "SRN3012TA", 3.00,  3.00, 3.20,  $u, 1.0,  3.2 ],
	[ "SRN3015"  , 3.00,  3.00,  $u , 1.0, 1.2,  2.7 ],
	[ "SRN3015TA", 3.00,  3.00, 3.20,  $u, 1.0,  3.2 ],
	[ "SRN4012T" , 4.00,  4.00, 4.20,  $u, 1.2,  4.2 ],
	[ "SRN4012TA", 4.00,  4.00, 4.20,  $u, 1.2,  4.2 ],
	[ "SRN4018"  , 4.00,  4.00, 4.55, 1.5,  $u,  3.6 ],
	[ "SRN4018TA", 4.00,  4.00, 4.20,  $u, 1.4,  4.2 ],
	[ "SRN4026"  , 4.00,  4.00, 4.55, 1.5,  $u,  3.5 ],
	[ "SRN5020"  , 5.00,  5.00, 6.30, 1.6,  $u,  5.7 ],
	[ "SRN5020TA", 5.00,  5.00,  $u , 1.5, 2.1,  4.7 ],
	[ "SRN5040"  , 5.00,  5.00, 5.10, 1.5,  $u,  4.0 ],
	[ "SRN5040TA", 4.95,  4.95,  $u , 1.5, 2.1,  4.2 ],
	[ "SRN6028"  , 6.00,  6.00, 6.30, 1.6,  $u,  5.7 ],
	[ "SRN6045"  , 6.00,  6.00,  $u , 2.0, 2.3,  6.0 ],
	[ "SRN6045HA", 6.00,  6.00, 6.40,  $u, 2.0,  6.4 ],
	[ "SRN6045TA", 6.00,  6.00, 6.50,  $u, 1.8,  5.1 ],
	[ "SRN8040"  , 8.15,  7.90,  $u , 2.6, 3.0,  8.2 ],
	[ "SRN8040TA", 8.00,  8.00, 8.50,  $u, 2.8,  6.6 ],

	# shielded types
	# name,          bx,    by,    tx ,   px,   sep,    py
	[ "SRE6603"  ,  6.60,  4.45,  6.86, 1.40,  4.06,  3.56 ],
	[ "SRR0603"  ,  6.50,  6.50,    $u, 1.65,  3.60,  2.50 ],
	[ "SRR0604"  ,  6.50,  6.50,    $u, 1.65,  3.60,  2.50 ],
	[ "SRR0745A" ,  7.30,  7.30,    $u, 1.50,  4.80,  2.40 ],
	[ "SRR0804"  , 10.50,  8.00,    $u, 2.50,  5.70,  2.20, 0], # oval
	[ "SRR0805"  , 10.50,  8.00,    $u, 2.50,  5.70,  2.20, 0 ], # oval
	[ "SRR0905"  ,  9.90,  9.90, 10.00,   $u,  2.80, 10.00, 0 ], # rund
	[ "SRR0906"  , ], # 8 pin
	[ "SRR0908"  , ], # 8 pin
	[ "SRR1003"  , 12.70, 10.30,    $u, 3.00,  7.30,  2.80, 0 ], # oval
	[ "SRR1005"  , 12.70, 10.00,    $u, 3.00,  7.30,  2.80, 0 ], # oval
	[ "SRR1050A" , 10.20, 10.00,    $u, 1.20,  7.80,  3.00 ],
	[ "SRR1205"  , 12.70, 12.70,    $u, 4.00,  6.00,  7.00 ],
	[ "SRR1206"  , 12.70, 12.70,    $u, 4.00,  6.00,  7.00 ],
	[ "SRR1208"  , 12.70, 12.70,    $u, 4.00,  6.00,  7.00 ],
	[ "SRR1210"  , 12.00, 12.00,    $u, 2.80,  7.30,  5.30 ],
	[ "SRR1210A" , 12.00, 12.00,    $u, 2.80,  7.30,  5.30 ],
	[ "SRR1240"  , 12.50, 12.50,    $u, 2.90,  6.80,  5.30 ],
	[ "SRR1260"  , 12.50, 12.50,    $u, 2.90,  6.80,  5.40 ],
	[ "SRR1260A" , 12.50, 12.50,    $u, 2.90,  6.80,  5.40 ],
	[ "SRR1280"  , 12.50, 12.50,    $u, 2.90,  6.80,  5.40 ],
	[ "SRR1280A" , 12.50, 12.50,    $u, 2.90,  6.80,  5.40 ],
	[ "SRR1305"  , ], # 4/5 pin
	[ "SRR1806"  , 18.30, 14.00,    $u, 3.00, 12.70,  2.90, 0 ], # oval
	[ "SRR3011"  ,  3.80,  3.80,    $u, 1.60,  1.10,  4.30, 0 ], # special, runt hål
	[ "SRR3818A" ,  3.80,  3.80,    $u, 1.60,  1.10,  4.30 ],
	[ "SRR4011"  ,  4.80,  4.80,    $u, 2.00,  1.50,  5.30, 0 ], # special, runt hål
	[ "SRR4018"  ,  4.80,  4.80,    $u, 2.00,  1.50,  5.30, 0 ], # special, runt hål
	[ "SRR4028"  ,  4.80,  4.80,    $u, 2.00,  1.50,  5.30, 0 ], # special, runt hål
	[ "SRR4528A" ,  5.00,  5.00,    $u, 1.60,  2.00,  5.30, 0 ], # special, runt hål
	[ "SRR4818A" ,  4.80,  4.80,    $u, 1.98,  1.17,  4.20 ],
	[ "SRR4828A" ,  4.80,  4.80,    $u, 1.98,  1.17,  4.20 ],
	[ "SRR5018"  ,  5.80,  5.80,    $u, 2.20,  1.90,  6.30, 0 ], # special, runt hål
	[ "SRR5028"  ,  5.80,  5.80,    $u, 2.20,  1.90,  6.30, 0 ], # special, runt hål
	[ "SRR6028"  ,  6.80,  6.80,    $u, 2.60,  2.10,  7.30, 0 ], # special, runt hål
	[ "SRR6038"  ,  6.80,  6.80,    $u, 2.60,  2.10,  7.30, 0 ], # special, runt hål
	[ "SRR6603"  ,  6.60,  4.40,  7.00,   $u,  4.10,  3.00, 0 ], # oval special lödöar
	[ "SRR7032"  ,  7.00,  7.00,  7.80, 1.80,  4.20,  2.40 ],
	[ "SRR7045"  ,  7.00,  7.00,  7.80, 1.80,  4.20,  2.40 ],
	[ "SRU1028"  , 10.00, 10.00,    $u, 1.80,  7.20,  3.60, 0 ], # 8-kantig
	[ "SRU1038"  , 10.00, 10.00,    $u, 1.80,  7.20,  4.00, 0 ], # 8-kantig
	[ "SRU1048"  , 10.00, 10.00,    $u, 1.80,  7.20,  3.60, 0 ], # 8-kantig
	[ "SRU1063"  , 10.00, 10.00,    $u, 1.80,  7.20,  3.80, 0 ], # 8-kantig, 4pin
	[ "SRU1063A" , 10.00, 10.00,    $u, 1.80,  7.20,  3.80, 0 ], # 8-kantig, 4pin
	[ "SRU2009"  ,  2.80,  2.80,    $u, 0.65,  2.10,  1.30, 0 ], # 8-kantig, special
	[ "SRU2011"  ,  2.80,  2.80,    $u, 0.65,  2.10,  1.30, 0 ], # 8-kantig, special
	[ "SRU2013"  ,  2.80,  2.80,    $u, 0.65,  2.10,  1.30, 0 ], # 8-kantig, special
	[ "SRU2016"  ,  2.80,  2.80,    $u, 0.65,  2.10,  1.30, 0 ], # 8-kantig, special
	[ "SRU3011"  ,  3.30,  3.30,  4.20, 1.20,  1.80,  1.30, 0 ], # 7-kantig, spetsig
	[ "SRU3014"  ,  3.30,  3.30,  4.20, 1.20,  1.80,  1.30, 0 ], # 7-kantig, spetsig
	[ "SRU3017"  ,  3.30,  3.30,  4.20, 1.20,  1.80,  1.30, 0 ], # 7-kantig, spetsig
	[ "SRU3028"  ,  3.30,  3.30,  4.20, 1.20,  1.80,  1.30, 0 ], # 7-kantig, spetsig
	[ "SRU5011"  ,  5.20,  5.20,    $u, 1.10,  3.70,  2.00, 0 ], # 8-kantig, 4pin
	[ "SRU5016"  ,  5.20,  5.20,    $u, 1.10,  3.70,  2.00, 0 ], # 8-kantig, 4pin
	[ "SRU5018"  ,  5.20,  5.20,    $u, 1.10,  3.70,  2.00, 0 ], # 8-kantig, 4pin
	[ "SRU5028"  ,  5.20,  5.20,    $u, 1.10,  3.70,  2.00, 0 ], # 8-kantig, 4pin
	[ "SRU6011"  ,  6.50,  6.50,    $u, 1.10,  4.90,  2.40, 0 ], # 8-kantig, 4pin
	[ "SRU6013"  ,  6.50,  6.50,    $u, 1.10,  4.90,  2.40, 0 ], # 8-kantig, 4pin
	[ "SRU6018"  ,  6.50,  6.50,    $u, 1.10,  4.90,  2.40, 0 ], # 8-kantig, 4pin
	[ "SRU6025"  ,  6.50,  6.50,    $u, 1.10,  4.90,  2.40, 0 ], # 8-kantig, 4pin
	[ "SRU8028"  ,  8.00,  8.00,    $u, 2.00,  5.80,  3.20, 0 ], # 8-kantig
	[ "SRU8043"  ,  8.00,  8.00,    $u, 2.00,  5.80,  3.20, 0 ], # 8-kantig
	[ "SRU8045A" ,  8.00,  8.00,    $u, 1.40,  6.20,  3.40, 0 ], # 8-kantig
    );
    for my $dr (@data) {
	my ($ser, $bx, $by, $tx, $px, $sx, $py, @rest) = @$dr;
	if (!defined($bx)) {
	    next;
	};
	if (@rest > 0) {
	    # TODO, do something about thoose with comments above
	    next;
	}
	if    (!defined($sx)) { $sx = $tx - 2*$px; }
	elsif (!defined($px)) { $px = ($tx - $sx)/2; }
	elsif (!defined($tx)) { $tx = $sx + 2*$px; }
	#print "$ser\n";
	my $cx = ($sx + $px)/2;
	my $cy = 0;
	my $doc = "# https://www.bourns.com/docs/product-datasheets/$ser\n";

	my @ext = (
	    [ ""  , 0 ],
	    [ "_a", 1.5 ], # add some for hand soldering
	);

	for my $er (@ext) {
	    my ($str, $val) = @$er;
	    my $file = "${name}_$ser$str.fp";
	    $cx += $val/2;
	    $px += $val;
	    element_start($file, $doc);
	    pad(-$cx, $cy, $px, $py);
	    pad( $cx, $cy, $px, $py);
	    pkg_body_rect([$bx, $by]);
	    element_stop();
	}
    }
}
#gen_bourns_SRN();

sub gen_bourns_SRF3216A() {
    my $name = "bourns_SRF3216A";
    my $doc = "# https://www.bourns.com/docs/product-datasheets/srf3216a.pdf\n";
    my $Xo = 3.7;
    my $xi = 1.9;
    my $Yo = 1.6;
    my $yi = 0.4;
    my $px = ($Xo - $xi)/2;
    my $py = ($Yo - $yi)/2;
    my $dx = ($Xo + $xi)/4;
    my $dy = ($Yo + $yi)/4;

    for my $rr (@radi) {
	my $radi = 0;
	if ($rr) { $radi = ipc_corner($py); }
	my $file = $name . $rr . ".fp";

	element_start($file, $doc);
	pad( -$dx,  $dy, $px, $py, undef, "", $radi);
	pad(  $dx,  $dy, $px, $py, undef, "", $radi);
	pad(  $dx, -$dy, $px, $py, undef, "", $radi);
	pad( -$dx, -$dy, $px, $py, undef, "", $radi);
	silk_bb(0.18);
	element_stop();
    }
}
#gen_bourns_SRF3216A();

sub gen_bourns_gdt_sm() {
    my $name = "bourns";
    my $doc;

    my @data = (
	#  $var,          $xi, $px, $py, $wy, $doc
	[ "2003xxSM"    , 2.5, 1.2, 4.0, 2.8, "# https/www.bourns.com/docs/product-datasheets/2003.pdf\\n" ],
	[ "2027-xx-SM"  , 4.6, 1.5, 8.6, 8.0, "# https://www.bourns.com/docs/product-datasheets/2027-xx-sm.pdf\n" ],
	[ "2029-xx-SMLF", 5.84-1.78, 1.78, 8.25, 7.9, "# https:/www.bourns.com/docs/product-datasheets/2029-xx-smlf.pdf\n" ],
	[ "2035-xx-SM"  , 4.0-1.3, 1.3, 5.6, 5.0, "# https://www.bourns.com/docs/product-datasheets/2035-xx-sm.pdf\n" ],
	[ "2051xxSM"    , 3.0, 1.5, 4.2, 3.2, "# https://www.bourns.com/docs/product-datasheets/2051.pdf\n" ],
	[ "2053xxSM"    , 3.5-1.3, 1.3, 5.0, 4.2, "# https://www.bourns.com/docs/product-datasheets/2053.pdf\n" ],
	[ "2055xxSM"    , 3.5-1.3, 1.3, 7.2, 6.2, "# https://www.bourns.com/docs/product-datasheets/2055.pdf\n" ],
    );
    for my $r (@data) {
	my ( $var, $xi, $px, $py, $wy, $doc) = @$r;
	my $dx = ($xi + $px)/2;
	my $cr = ipc_corner($px);
	my $sx = ($xi - 2* $clearance);
	my $file = sprintf "%s_%s.fp", $name, $var;
	element_start($file, $doc);
	pad( -$dx, 0, $px, $py, undef, "", $cr);
	pad(  $dx, 0, $px, $py, undef, "", $cr);
	silk_start(-$sx/2, -$wy/2);
	silk_rline($sx, 0);
	silk_start(-$sx/2, $wy/2);
	silk_rline($sx, 0);
	element_stop();
    }
}
#gen_bourns_gdt_sm();

sub gen_yageo_chip_resistor() {
    my $str_reflow = # 0100 ch. to 01005
"PRODUCT SIZE FOOTPRINT DIMENSIONS                          Unit: mm
CODE         A                B    C    D         Placement accuracy
0075         0.34             0.14 0.1  0.15                     N/A
01005         0.48             0.12 0.18 0.18~0.23                N/A
0201         1.0              0.3  0.35 0.4                      N/A
0402         1.5              0.5  0.5  0.6                    ± 0.15
0603         2.6              0.8  0.9  0.8                    ± 0.25
0805         3.0              1.2  0.9  1.2                    ± 0.25
1206         4.2              2.2  1.0  1.5                    ± 0.25
1210         4.2              2.2  1.0  2.4                    ± 0.25
1218         4.2              2.2  1.0  4.8                    ± 0.25
2010         6.1              3.3  1.4  2.4                    ± 0.25
2512         8.0              4.4  1.8  4.0                    ± 0.25
";
    my $str_wave =
"PRODUCT SIZE FOOTPRINT DIMENSIONS                     Unit: mm
CODE         A                B    C    D    Placement accuracy
0603         2.70             0.90 0.90 0.80              ± 0.25
0805         3.30             1.30 1.00 1.30              ± 0.25
1206         4.70             2.50 1.10 1.70              ± 0.25
1210         4.70             2.50 1.10 2.50              ± 0.25
1218         4.70             2.50 1.10 4.80              ± 0.25
2010         6.40             4.20 1.10 2.50              ± 0.25
2512         8.20             5.50 1.35 3.20              ± 0.25
";

    my $doc = "# http/www.yageo.com/exep/pages/download/literatures/PYu-R_Mount_10.pdf\n";
    my %dim;
    # silk widths
    my $sw = 0.2;
    my $sc = 0.05;

    for my $line (grep { m/^\d/ } split(/\n/, $str_reflow)) {
	my ($in, $A, $B, $C, $D, $pa) = split(/\s+/, $line);
	if ($D =~ m/~/) {
	    my ($min, $max) = split(/~/, $D);
	    $D = $max;
	}
	my $sz = chip_mil2mm($in);
	if (defined($sz)) { # skip "0075" for the moment
	    $dim{$sz . "refl"} = [ $B, $C, $D ];
	}
    }
    for my $line (grep { m/^\d/ } split(/\n/, $str_wave)) {
	my ($in, $A, $B, $C, $D, $pa) = split(/\s+/, $line);
	my $sz = chip_mil2mm($in);
	$dim{$sz . "wave"} = [ $B, $C, $D ];
    }
    for my $sz (sort keys %dim) {
	my ($B, $C, $D) = @{$dim{$sz}};
	my $xc = ($B + $C)/2;
	my $wx = substr($sz, 0, 2)/10;
	my $wy = substr($sz, 2, 2)/10;
	my $min_w = $C < $D ? $C : $D;
	my $cr = ipc_corner($min_w);
	my $xi = $B/2 - $mask_gap - $sw/2;
	my $yi = $wy/2;
	#print "$sz $B $C $D $wx $wy $min_w\n";

	for my $opt (("r", "")) {
	    my $file = sprintf "yageo_%s%s.fp", $sz, $opt;
	    element_start($file, $doc);
	    pad( -$xc, 0, $C, $D, undef, "", $cr);
	    pad(  $xc, 0, $C, $D, undef, "", $cr);

	    if ($xi > 0) {
		silk_width($sw);
		silk_start(-$xi, -$yi);
		silk_line ( $xi, -$yi);
		silk_start(-$xi,  $yi);
		silk_line ( $xi,  $yi);
	    }

	    silk_width($sc);
	    silk_bb(0.20);
	    element_stop();
	    $cr = 0;
	}
    }
    silk_width();
}
#gen_yageo_chip_resistor();

sub gen_yageo_chip_resistor_array() {
    my $str =
"PRODUCT SIZE CODE TYPE      FOOTPRINT DIMENSIONS                      Unit: mm
                            A                 B           F           P
0404              ATV321    0.50 ± 0.10       0.42 ± 0.05 1.80 ± 0.20 0.65 ± 0.05
2 x 0201 (4P2R)   YC102     0.30 ± 0.10       0.30 ± 0.05 0.90 ± 0.20 0.50 ± 0.05
4 x 0201 (8P4R)   YC104     0.30 ± 0.10       0.20 ± 0.05 0.90 ± 0.20 0.40 ± 0.05
2 × 0402 (4P2R)   YC/TC122  0.50 ± 0.10       0.30 ± 0.05 1.80 ± 0.20 0.67 ± 0.05
4 × 0402 (8P4R)   YC/TC124  0.50 ± 0.10       0.30 ± 0.05 1.80 ± 0.20 0.50 ± 0.05
2 × 0603 (4P2R)   YC162     0.80 ± 0.10       0.45 ± 0.05 2.60 ± 0.20 0.80 ± 0.05
4 × 0603 (8P4R)   YC/TC164  0.80 ± 0.10       0.45 ± 0.05 2.60 ± 0.20 0.80 ± 0.05
1220 (8P4R)       YC324     2.20 ± 0.10       0.71 ± 0.05 3.90 ± 0.20 1.27 ± 0.05
0616 (16P8R)      YC248     0.50 ± 0.10       0.30 ± 0.05 1.80 ± 0.20 0.50 ± 0.05
0612 (10P8R)      YC158     0.80 ± 0.10       0.35 ± 0.05 2.60 ± 0.20 0.64 ± 0.05
1225 (10P8R)      YC358     1.60 ± 0.10       0.90 ± 0.05 3.90 ± 0.20 1.27 ± 0.05
";
    my $doc = "# http://www.yageo.com/exep/pages/download/literatures/PYu-R_Mount_10.pdf\n";
    my $sw = 0.2;
    silk_width($sw);

    for my $line (grep { m/^\d/ } split(/\n/, $str)) {
	$line =~ m/\((\d+)P\d+R.*\)\s*(.*)/;
	next unless (defined($1)); # don't know about the ATV321
	my $N = $1;
	my $dims = $2;

	my @fld = split(/\s+/, $dims);
	my ($type, $A, $B, $F, $P) = @fld[0,1,4,7,10];
	$type =~ s|/TC||;
	#print "$N / $type, $A, $B, $F, $P\n";
	my $xc = ($F + $A)/4;
	my $px = ($F - $A)/2;
	my $py = $B;
	my $min_w = $px < $py ? $px : $py;
	my $CR = ipc_corner($min_w);
	my $ymid = -($N/2 - 1)/2 * $P;

	for my $opt (("l", "r", "")) {
	    my $addlen = 0;
	    my $cr = 0;
	    if ($opt eq "") { } # as per yageo spec
	    elsif ($opt eq "r") { $cr = $CR; } # same with rounded pads
	    elsif ($opt eq "l") { $cr = $CR; $addlen = 1; } # same with longer pads
	    my $file = sprintf "yageo_%s%s.fp", $type, $opt;
	    element_start($file, $doc);
	    my $num = 1;
	    for (my $ix = 0; $ix < $N/2; $ix++) {
		pad( -$xc-$addlen/2, $ymid + $ix * $P, $px+$addlen, $py, undef, "", $cr);
	    }
	    for (my $ix = $N/2 - 1; $ix >= 0; $ix--) {
		pad(  $xc+$addlen/2, $ymid + $ix * $P, $px+$addlen, $py, undef, "", $cr);
	    }
	    bb_tlcorner($bounding_box[0]);
	    element_stop();
	}
    }
    silk_width();
}
#gen_yageo_chip_resistor_array();

sub gen_vishay_smd() {
    my $doc = "# p.109 http://images.vishay.com/books/VSE-DB0010-0611_SMD_Resistors_Arrays_and_Networks_INTERACTIVE.pdf\n";
    my $str1 = # component dimensions, L W and T1 defines component contact area size
"inch metr.   L              W         H         T1            T2
0201 0525  0.6±0.05       0.3±0.05  0.23±0.05 0.15±0.05     0.15+0.05-0.10
0402 1005  1.0±0.05       0.5±0.05  0.35±0.05 0.25±0.05     0.2±0.1
0603 1608  1.55+0.10-0.05 0.85±0.1  0.45±0.05 0.3±0.2       0.3±0.2
0805 2012  2.0+0.20-0.10  1.25±0.15 0.45±0.05 0.3+0.20-0.10 0.3±0.2
1206 3216  3.2+0.10-0.20  1.6±0.15  0.55±0.05 0.45±0.2      0.4±0.2
1210 3225  3.2±0.2        2.5±0.2   0.55±0.05 0.45±0.2      0.4±0.2
1218 3246  3.2+0.10-0.20  4.6±0.15  0.55±0.05 0.45±0.2      0.4±0.2
2010 5025  5.0±0.15       2.5±0.15  0.6±0.1   0.6±0.2       0.6±0.2
2512 6332  6.3±0.2        3.15±0.15 0.6±0.1   0.6±0.2       0.6±0.2
";
    my $str2 = # recommended pad sizes
"         reflow          wave
metr. a    b    l    a     b    l
0525 0.28 0.43 0.23
1005 0.4  0.6  0.5
1608 0.5  0.9  1.0   0.9  0.9  1.0
2012 0.7  1.3  1.2   0.9  1.3  1.3
3216 0.9  1.7  2.0   1.1  1.7  2.3
3225 0.9  2.5  2.0   1.1  2.5  2.2
3246 1.05 4.9  1.9   1.25 4.8  1.9
5025 1.0  2.5  3.9   1.2  2.5  3.9
6332 1.0  3.2  5.2   1.2  3.2  5.2
";

    for my $line (grep { m/^\d/ } split(/\n/, $str2)) {
	my ($sz, $ra, $rb, $rl, $wa, $wb, $wl) = split(/\s+/, $line);
	my $file = sprintf "vishay_%s_v.fp", $sz; # v for vendor recommended
	element_start($file, $doc);
	my $xc = ($rl + $ra)/2;
	pad( -$xc, 0, $ra, $rb);
	pad(  $xc, 0, $ra, $rb);
	silk_bb();
	element_stop();
    }
}
#gen_vishay_smd();

sub gen_vishay_chip_resistor_array() {
    my (    $type,     $G, $Y, $X,  $U, $Z, $I, $P) =
	qw/ ACAS_0612 0.7 0.7 0.64 0.5 2.1 0.3 0.8/;

    my $doc = "# https://www.vishay.com/docs/28751/acasprec.pdf
# https://www.farnell.com/datasheets/2612835.pdf\n";
    my $file = sprintf "vishay_%s.fp", $type;

    element_start($file, $doc);
    my $y  = ($Y + $G)/2;
    my $x1 = $P/2 + $U/2 + $I + $X/2;
    my $x2 = $P/2;

    pad( -$x1,  $y, $X, $Y);
    pad( -$x2,  $y, $U, $Y);
    pad(  $x2,  $y, $U, $Y);
    pad(  $x1,  $y, $X, $Y);

    pad(  $x1, -$y, $X, $Y);
    pad(  $x2, -$y, $U, $Y);
    pad( -$x2, -$y, $U, $Y);
    pad( -$x1, -$y, $X, $Y);

    element_stop();
}
#gen_vishay_chip_resistor_array();

sub gen_vishay_melf() {
    my $name = "Vishay";
    my $doc = "# http://www.vishay.com/docs/28714/melfpre.pdf\n";

    my @data = (
	[ qw/ MMU 0102 2.2 1.1 refl 1.1 0.8 1.3 2.7 / ],
	[ qw/ MMA 0204 3.6 1.4 refl 1.7 1.2 1.6 4.1 / ],
	[ qw/ MMB 0207 5.8 2.2 refl 3.2 1.7 2.4 6.6 / ],

	[ qw/ MMU 0102 2.2 1.1 wave 0.7 1.2 1.5 3.1 / ],
	[ qw/ MMA 0204 3.6 1.4 wave 1.5 1.5 1.8 4.5 / ],
	[ qw/ MMB 0207 5.8 2.2 wave 2.8 2.1 2.6 7.0 / ],
    );

    for my $rr (@data) {
	my $file;
	my ($type, $size, $L, $D, $ss, $G, $Y, $X, $Z) = @$rr;
	my $body = [ $L, $D ];

	$file = "${name}_${type}_${size}_$ss.fp";
	element_start($file, $doc);
	my $xc = ($G + $Y)/2;
	pad( -$xc, 0, $Y, $X);
	pad(  $xc, 0, $Y, $X);
	my @bbw = bb_enlarge($silk_w/2, @bounding_box);
	silk_crect($origin, $body, 0, \@bbw);
	element_stop();
    }
}
#gen_vishay_melf();

sub gen_fsm2jsma() {
    element_start("fsm2jsma.fp", "# TE CONNECTIVITY / ALCOSWITCH - FSM2JSMA - TACTILE SWITCH, SPNO, SMD
# http://www.farnell.com/datasheets/29696.pdf
");
    my $wx = 1.4;
    my $x  = (3.10 + $wx)/2;

    my $wy = 2.10;
    my $y  = (7.0 + $wy)/2;

    pad( -$x, -$y, $wx, $wy);
    use_same_pin_no();
    pad( -$x,  $y, $wx, $wy);
    pad(  $x, -$y, $wx, $wy);
    use_same_pin_no();
    pad(  $x,  $y, $wx, $wy);

    silk_bb(0.32);
    element_stop();
}
#gen_fsm2jsma();

sub gen_multicomp_2Mxx() {
    my $name = "multicomp_2M";
    my $doc  =
"# http://www.farnell.com/datasheets/1375607.pdf
# Multicomp Sub-Miniature Toggle Switches
";

    my $px  = 2.54;
    my $dy2 = 4.0/2;
    my $dy6 = -2.54;
    my $dyM = 5.08;
    my $bx  = 8.13/2;

    my @model = qw/ Sx Dx /;
    my @mnt   = qw/ M2 M6 /;
    my $drill = 1.1; #lead_to_drill(0.76, 0.51);
    my @thickness = drill2thickness($drill);

    $round_first_pin = 1;
    for my $model (@model) {
	for my $mnt (@mnt) {
	    for (my $tx = 0; $tx < @thickness; $tx++) {
		my $limit_radius = $thickness[$tx] + $mask_gap;
		if ($px < $limit_radius) { next; }
		my $file = sprintf("%s%s-Tx-Bx-%s_%s.fp", $name, $model, $mnt, thickness_suffix($tx));
		#print "$file: $px $limit_radius\n";

		element_start($file, $doc);
		if      ($mnt eq "M2") {
		    if ($model eq "Sx") {
			for (my $ix = -1; $ix <= 1; $ix++) { pin( -$ix * $px, 0, $drill, $thickness[$tx]); }
		    } else {
			for (my $ix = -1; $ix <= 1; $ix++) { pin( -$ix * $px,  $dy2, $drill, $thickness[$tx]); }
			for (my $ix = -1; $ix <= 1; $ix++) { pin( -$ix * $px, -$dy2, $drill, $thickness[$tx]); }
		    }
		} elsif ($mnt eq "M6") {
		    if ($model eq "Sx") {
			for (my $ix = -1; $ix <= 1; $ix++) { pin( -$ix * $px, 0, $drill, $thickness[$tx]); }
			pin(-$px, $dyM, $drill, $thickness[$tx], "M", "", "M");
			pin( $px, $dyM, $drill, $thickness[$tx], "M", "", "M");
		    } else {
			for (my $ix = -1; $ix <= 1; $ix++) { pin( -$ix * $px,    0, $drill, $thickness[$tx]); }
			for (my $ix = -1; $ix <= 1; $ix++) { pin( -$ix * $px, $dy6, $drill, $thickness[$tx]); }
			pin(-$px, $dyM, $drill, $thickness[$tx], "M", "", "M");
			pin( $px, $dyM, $drill, $thickness[$tx], "M", "", "M");
		    }
		}
		my @bbw = bb_enlarge($silk_w/2,@bounding_box);
		if      ($mnt eq "M2") {
		    if ($model eq "Sx") {
			silk_crect($origin, [8.13, 5.08], 0, \@bbw);
		    } else {
			silk_crect($origin, [8.13, 9.14], 0, \@bbw);
		    }
		    silk_circle($origin, 6.0/2, 0, 360, \@bbw);
		} elsif ($mnt eq "M6") {
		    my $yp = $dyM+4.01;
		    silk_rect([-$bx,0], [$bx,$yp], 0, \@bbw);
		    silk_rect([-5/2,$yp], [5/2,$yp+5.59], 0, \@bbw);
#		    if ($model eq "Sx") {
#		    } else {
#		    }
		}
		element_stop();
	    }
	}
    }
    $round_first_pin = 0;
}
#gen_multicomp_2Mxx();

sub gen_so_xx() {
    my $cnt_min = 4;
    my $cnt_max = 16;
    my $w_max = 6.2;
    my $w_min = 5.8;
    my $pitch = 1.27;
    my $toe_w = 0.51;
    my $toe_max = 1.27;
    my $cnt;
    my ($xc, $xl) = ipc_get_cl($w_max, $w_min, $toe_max, @ipc_gw_LA);
    my $yl = $toe_w + 2*$ipc_gw_LA[$SIDE];

    for my $rr (@radi) {
	my $radi = 0;
	if ($rr) { $radi = ipc_corner($yl); }
	for ($cnt = $cnt_min; $cnt <= $cnt_max; $cnt +=2) {
	    my $num = sprintf("%02d", $cnt);
	    element_start("so_${num}_a$rr.fp", "# $cnt-lead so according to Texas Instruments
# http://focus.ti.com/lit/ds/symlink/sn65176b.pdf page 18
");
	    my $sc = $cnt/2;
	    my $first = 0.2;

	    # pin #1 indicator in silk
	    my $tt = mk_mm(-$xc - $xl/2 + 0.5);
	    pr("ElementArc [ $tt -0.9mm 0.1mm 0.1mm  0 360 0.35mm ]\n");

	    my $ix;
	    pad(-$xc - $first/2, 0, $xl + $first, $yl, undef, "", $radi);
	    for ($ix = 1; $ix < $sc; $ix++) { # left side
		pad(-$xc, $ix * $pitch, $xl, $yl, undef, "", $radi);
	    }
	    for ($ix = $sc-1; $ix >= 0; $ix--) { # right side
		pad( $xc, $ix * $pitch, $xl, $yl, undef, "", $radi);
	    }

	    silk_bb(0.32);
	    element_stop();
	}
    }
}
#gen_so_xx();

sub gen_tssop_ti() {
  my $cnt_min = 8;
  my $cnt_max = 8;
  my $w_max = 6.6;
  my $w_min = 6.2;
  my $pitch = 0.65;
  my $toe_w = 0.3;
  my $toe_max = 0.75;
  my $cnt;
  my ($xc, $xl) = ipc_get_cl($w_max, $w_min, $toe_max, @ipc_gw_LA);
  my $yl = $toe_w + 2*$ipc_gw_LA[$SIDE];

    for my $rr (@radi) {
	my $radi = 0;
	if ($rr) { $radi = ipc_corner($yl); }
	for ($cnt = $cnt_min; $cnt <= $cnt_max; $cnt++) {
	    element_start("tssop_${cnt}_ti$rr.fp", "# $cnt-lead tssop according to Texas Instruments
# http://www.ti.com/lit/ds/symlink/sn65240.pdf page 11/12
");
	    my $sc = $cnt/2;
	    my $first = 0.2;

	    # pin #1 indicator in silk
	    my $tt = mk_mm(-$xc - $xl/2 + 0.5);
	    pr("ElementArc [ $tt -0.9mm 0.1mm 0.1mm  0 360 0.35mm ]\n");

	    my $ix;
	    pad(-$xc - $first/2, 0, $xl + $first, $yl, undef, "", $radi);
	    for ($ix = 1; $ix < $sc; $ix++) { # left side
		pad(-$xc, $ix * $pitch, $xl, $yl, undef, "", $radi);
	    }
	    for ($ix = $sc-1; $ix >= 0; $ix--) { # right side
		pad( $xc, $ix * $pitch, $xl, $yl, undef, "", $radi);
	    }

	    silk_bb(0.32);
	    element_stop();
	}
    }
}
#gen_tssop_ti();

sub gen_ssop_20_uchip() {
  element_start("ssop_20_microchip.fp", "# 20-lead ssop according to Microchip
# http://ww1.microchip.com/downloads/en/DeviceDoc/22228B.pdf page 37
");
  my $E = 0.65;
  my $C = 7.5 + 0.15; # inside dim ok, but I want pads to stick out more
  my $Y1 = 0.45;
  my $X1 = 1.75 + 0.3;
  my $first = 0.2;

  # pin #1 indicator in silk
  my $tt = mk_mm(-$C/2 - $X1/2 + 0.5);
  pr("ElementArc [ $tt -0.9mm 0.1mm 0.1mm  0 360 0.35mm ]\n");

  my $ix;
  pad(-$C/2 - $first/2, 0, $X1 + $first, $Y1);
  for ($ix = 1; $ix < 10; $ix++) { # pin 1..10
    pad(-$C/2, $ix * $E, $X1, $Y1);
  }
  for ($ix = 9; $ix >= 0; $ix--) { # pin 11..20
    pad( $C/2, $ix * $E, $X1, $Y1);
  }
  silk_bb(0.32);
  element_stop();
}

#gen_ssop_20_uchip();

sub gen_d2pac_7pin() {
  element_start("d2pac_7pin.fp", "# D2Pac
# IRF1324S-7PPbF
# http://www.farnell.com/datasheets/28247.pdf
# origo at top center
");
  my $y = 16.3 - 3.2/2;
  pad( -3*1.27, $y, 0.9, 3.2 );
  pad( -2*1.27, $y, 0.9, 3.2 );
  pad( -1*1.27, $y, 0.9, 3.2 );
  inc_pin_no(); # no #4 pad
  pad(  1*1.27, $y, 0.9, 3.2 );
  pad(  2*1.27, $y, 0.9, 3.2 );
  pad(  3*1.27, $y, 0.9, 3.2 );
  pr("\n");
  pad(0, 8.15/2, 10.8, 8.15 );
  pr("\n");
  silk_bb(0.32);
  element_stop();
}

#gen_d2pac_7pin();

sub gen_sot23_to236() {
  my $body = [ 2.9, 1.3 ];
  element_start("sot23_to236.fp", "# sot23 3 leads
# http://www.fairchildsemi.com/dwg/MA/MA03D.pdf
");
  pad(-1.9/2,  2.2/2, 1.0, 1.4);
  pad(+1.9/2,  2.2/2, 1.0, 1.4);
  pad(     0, -2.2/2, 1.0, 1.4);
  my @bbw = bb_enlarge($silk_w/2, @bounding_box);
  silk_crect($origin, $body, 0, \@bbw);
  element_stop();
}
#gen_sot23_to236();

sub gen_sot23_5() {
  element_start("sot23_5.fp", "# sot23 5 leads
# http://www.farnell.com/datasheets/77628.pdf
");
  my $p = 0.95;
  my $x = 1.2;
  pad( -$x, -$p, 1.4, 0.6);
  pad( -$x,   0, 1.4, 0.6);
  pad( -$x,  $p, 1.4, 0.6);

  pad(  $x,  $p, 1.4, 0.6);
  pad(  $x, -$p, 1.4, 0.6);

  silk_bb(0.32);
  element_stop();
}
#gen_sot23_5();

sub gen_sot23_6() {
  my $p = 0.95;
  my $x = 1.2;
    for my $rr (@radi) {
	my $radi = 0;
	if ($rr) { $radi = ipc_corner(0.6); }

	element_start("sot23_6$rr.fp", "# sot23 6 leads
# http://ww1.microchip.com/downloads/en/DeviceDoc/25004A.pdf
");
	pr("ElementArc [ -1.6mm -1.8mm 0.1mm 0.1mm  0 360 0.35mm ]\n");

	pad( -$x, -$p, 1.4, 0.6, undef, "", $radi);
	pad( -$x,   0, 1.4, 0.6, undef, "", $radi);
	pad( -$x,  $p, 1.4, 0.6, undef, "", $radi);

	pad(  $x,  $p, 1.4, 0.6, undef, "", $radi);
	pad(  $x,   0, 1.4, 0.6, undef, "", $radi);
	pad(  $x, -$p, 1.4, 0.6, undef, "", $radi);

	silk_bb(0.32);
	element_stop();
    }
}
#gen_sot23_6();

sub gen_molex_537548_0504() {
  my $ix;
  my $x = -6;
  element_start("molex_537548_0504.fp", "# molex smt board to board connector plug, 50 ways
# http://www.molex.com/pdm_docs/sd/537480504_sd.pdf
");

  for ($ix = 0; $ix < 25; $ix++) {
    pad( $x, -1.7, 0.25, 1.2);
    pad( $x,  1.7, 0.25, 1.2);
    $x += 0.5;
  }
  pr("ElementLine[  -7.65mm -2.15mm    8.15mm -2.15mm  0.25mm ]\n");
  pr("ElementLine[   8.15mm -2.15mm    8.15mm  2.15mm  0.25mm ]\n");
  pr("ElementLine[   8.15mm  2.15mm   -8.15mm  2.15mm  0.25mm ]\n");
  pr("ElementLine[  -8.15mm  2.15mm   -8.15mm -1.65mm  0.25mm ]\n");
  pr("ElementLine[  -8.15mm -1.65mm   -7.65mm -2.15mm  0.25mm ]\n");
  element_stop();
}
#gen_molex_537548_0504();

sub gen_panasonic_ellatp() {
  element_start("panasonic_ellatp.fp", "# panasonic SMD Choke Coils
# Series: P
# Type: ELLATP
# https://www1.elfa.se/data1/wwwroot/assets/datasheets/ELLATPxxxB.pdf
");
  my @x = (12, 8.3);
  my $mid = ($x[0] + $x[1]) / 4;
  my $th = ($x[0] - $x[1]) / 2;
  pad(-$mid, 0,  $th, 3);
  pad(+$mid, 0,  $th, 3);

  my $sqrt2 = sqrt(2);
  my $ymax = $sqrt2 * 10 / 2;
  my $aflat = 2.5/2;
  my $bflat = 2.3/2;

  silk_width(0.32);
  silk_start(0,-$ymax);
  silk_line(-$ymax + $aflat, -$aflat);
  silk_line(-$ymax + $aflat, +$aflat);
  silk_line(-$bflat, $ymax - $bflat);
  silk_line( $bflat, $ymax - $bflat);
  silk_line( $ymax - $aflat, +$aflat);
  silk_line( $ymax - $aflat, -$aflat);
  silk_line(0,-$ymax);

  element_stop();
}
#gen_panasonic_ellatp();

sub gen_panasonic_ell6xp() {
  element_start("panasonic_ell6xp.fp", "# panasonic SMD Choke Coils
# Series: G
# Type: ELL6GG ELL6PG
# http://www.farnell.com/datasheets/391793.pdf
");
  my $x = (2.1+2.9)/2;
  my $px = 2.1;
  my $py = 2.7;
  pad(-$x, 0, $px, $py);
  pad(+$x, 0, $px, $py);
  pkg_body_rect([6,6],1);
  element_stop();
}
#gen_panasonic_ell6xp();

sub gen_wuerth_we_pd() {
    # arrgh..., why can't Wuerth have a page of all used land patterns
    # like other manufacturer
    my @data = (
	# [ body x y   px   py  inner outer  [ size, art.nr, ...], ... ]
	[ "5962", 5.9,  6.2,  1.9, 1.85, 2.5,  6.2,
	   [ 6033, 7447785001, 7447785002, 7447785003, 7447785004, 7447785006,
	     744778510, 7447785115, 7447785122, 7447785127, 7447785133, 7447785147, 744778520, ],
	   [ 6050, 7447786001, 7447786002, 7447786004, 7447786006, 7447786008,
	     744778610, 7447786122, 7447786147, ],
        ],
	[ "7373a",  7.3,  7.3,  1.7, 2.0 , 4.0,  8.0,
	   [ 7332, 7447789001, 7447789002, 7447789003, 7447789004, 744778910, 7447789112,
	     7447789115, 7447789118, 7447789122, 7447789127, 7447789133, 7447789139,
	     7447789147, 7447789156, 7447789168, 7447789182, 744778920, 7447789212, 7447789215,  ],
	   [ 7345, 7447779001, 74477790015, 7447779002, 7447779003, 7447779004, 744777910,
	     7447779112, 7447779115, 7447779118, 7447779122, 7447779127, 7447779133, 
	     7447779139, 7447779147, 7447779156, 7447779168, 7447779182, 744777920, 7447779212, ],
        ],
	[ "7373b", 7.3,  7.3,  2.2, 1.6 , 4.8,  8.0,
	  [ 7332, 744778001, 744778002, 744778003, 744778004, 744778005, 74477810, 744778112, 744778115,
	    744778118, 744778122, 744778127, 744778133, 744778139, 744778147, 744778156, 744778168, 744778182,
	    74477820, 744778212, 744778215, 7447789006, ],
	  [ 7345, 744777001, 744777002, 744777003, 74477710, 744777112, 744777115, 744777118, 744777122,
	    744777127, 744777133, 744777139, 744777147, 744777156, 744777168, 744777182, 74477720, 744777212,
	    744777215, 7447779006, 7447779008, ],

        ],
	[ "7374", 7.3,  7.4,  2.2, 1.6 , 4.8,  8.0,
	  [ 7332, 7447783015, 7447783022, 7447783033, 7447783047, 7447783068, 7447783100, 7447783101, 7447783220,
	    7447783330, 7447783470, 7447783680, ],
	  [ 7345, 744777004, 7447773010, 7447773022, 7447773033, 7447773047, 7447773062, 7447773100, 7447773101,
	    7447773150, 7447773220, 7447773330, 7447773470, 7447773680, 7447783150, ],
        ],
	[ "1010", 10.0, 10.0,  3.5, 2.0 , 7.0, 11.0,
	  [ 1030, 7447713015, 7447713022, 7447713033, 7447713047, 7447713082, 7447713100, 7447713101, 7447713121,
	    7447713150, 7447713151, 7447713220, 7447713330, 7447713470, 7447713680, 7447713820, 7447714015,
	    7447714022, 7447714033, 7447714047, 7447714056, 7447714068, ],
	  [ 1050, 7447714100, 7447714101, 7447714150, 7447714151, 7447714220, 7447714270, 7447714330, 7447714470,
	    7447714560, 7447714680, 7447714820, 7447714820, ],
	],
	[ "1212", 12.0, 12.0,  5.4, 2.9 , 7.0, 12.8,
	  [ 1210, 7447709001, 7447709002, 7447709003, 7447709004, 7447709006, 7447709100, 7447709101, 7447709150,
	    7447709151, 7447709220, 7447709270, 7447709330, 7447709390, 7447709470, 7447709680, 7447709820, ],
	  [ 1245, 7447715001, 7447715002, 7447715003, 7447715004, 7447715006, 7447715100, 7447715101, 7447715120,
	    7447715180, 7447715220, 7447715330, 7447715470, 7447715906, 7447715910 ],
	  [ 1260, 7447706015, 7447706022, 7447706033, 7447706047, 7447706062, 7447706100, 7447706101, 7447706150,
	    7447706220, 7447706330, 7447706470, 7447706680, 744771001, 744771002, 744771003, 744771004, 744771006,
	    744771008, 74477110, 744771112, 744771115, 744771118, 744771122, 744771127, 744771133, 744771139,
	    744771147, 744771156, 744771168, 744771182, 744771182, 74477120, 744771212, 744771215 ],
	  [ 1280, 74477001, 744770015, 74477002, 74477003, 74477004, 74477005, 74477006, 74477007, 74477008,
	    74477009, 74477010, 744770112, 744770115, 744770118, 744770122, 744770127, 744770133, 744770139,
	    744770147, 744770156, 744770168, 744770182, 74477020, 744770215, 7447707015, 7447707022, 7447707033,
	    7447707047, 7447707068, 7447707100, 7447707101, 7447707150, 7447707220, 7447707330, 7447707470, 7447707680 ],
        ],
	[ "1515", 15.0, 15.0,  5.8, 3.3, 9.5, 0,
	  [ 1510, 7447704150, 7447704220 ],
        ],
    );

    for my $r (@data) {
	my ($sz, $bx, $by, $px, $py, $inner, $outer, @list) = @$r;
	my $doc = "# https://www.we-online.com/catalog/datasheet/<order_number>.pdf\n";
	my $xtr = "";
	for my $tt (@list) {
	    my ($type, @order) = @$tt;
	    my @srt = sort @order;
	    my $aa = join(", ", @order);
	    my $bb = join(", ", @srt);
	    if ($aa ne $bb) {
		warn "$sz [ $type, $bb ],\n";
	    }
	    $xtr .= "# size/type $type, order number: $bb\n";
	}
	if ($xtr) { $xtr .= "# and possible others also\n"; }
	my %ext = (a => 0.0, b => 0.5, c => 1.0);
	for my $k (keys %ext) {
	    my $ext = $ext{$k};
	    my $cc = ($py + $ext + $inner)/2;
	    my $file = "wuerth_we_pd_${sz}_$k.fp";
	    element_start($file, $doc);
	    pad(-$cc, 0, $py+$ext, $px);
	    pad(+$cc, 0, $py+$ext, $px);
	    pkg_body_rect([$by,$bx],1);
	    element_stop($xtr);
	}
    }
}
#gen_wuerth_we_pd();

sub gen_kemet_t520() {
    my $doc = 'http://www.kemet.com/Lists/ProductCatalog/Attachments/421/KEM_T2015_T520.pdf';
    # dimensions table, p4
    # in contrast to radial electrolytes, theese are marked on the positive side
    my $dim_str =  # B P R == 0 => no bewel or cutout, said N/A in table
"KEMET EIA       L   W   H    F   S   B    X    P   R    T    A  Weight
A     3216_18  3.2 1.6 1.6  1.2 0.8 0.4  0.10 0.4 0.4  0.13 1.2  53.16
B     3528_21  3.5 2.8 1.9  2.2 0.8 0.4  0.10 0.5 1.0  0.13 1.9  94.85
C     6032_28  6.0 3.2 2.5  2.2 1.3 0.5  0.10 0.9 1.0  0.13 2.9 184.14
D     7343_31  7.3 4.3 2.8  2.4 1.3 0.5  0.10 0.9 1.0  0.13 3.6 434.83
H     7360_20  7.3 6.0 1.9  4.1 1.3  0   0.10  0   0   0.13 3.3 384.64
L     6032_19  6.0 3.2 1.8  2.2 1.3  0   0.05  0   0   0.13 2.5 186.68
M     3528_15  3.5 2.8 1.4  2.2 0.8  0   0.05  0   0   0.13 1.1  97.99
Q     7343_12  7.3 4.3 1.1  2.4 1.3  0   0.05  0   0   0.13 3.8 170.35
T     3528_21  3.5 2.8 1.1  2.2 0.8  0   0.05  0   0   0.13 1.9  54.84
U     6032_15  6.0 3.2 1.4  2.2 1.3  0   0.05  0   0   0.13 2.9 117.36
V     7343_19  7.3 4.3 1.8  2.4 1.3  0   0.05  0   0   0.13 3.6 274.30
W     7343_15  7.3 4.3 1.4  2.4 1.3  0   0.05  0   0   0.13 3.6 222.95
X     7343_43  7.3 4.3 4.0  2.4 1.3 0.5  0.10 1.7 1.0  0.13 3.6 553.96
Y     7343_40  7.3 4.3 3.8  2.4 1.3 0.5  0.10 1.7 1.0  0.13 3.8 493.99
";
    my @dim;
    for my $str (split(/\n/, $dim_str)) {
	my @fld = split(/\s+/, $str);
	push @dim, [ @fld ];
    }
    shift @dim;

    # Table 2, p16 (but sorted by case, i.e. H move up two lines)
    my @density = qw/a b c/;
    my @dens_txt = (
	"Maximum (Most) Land Protrusion",
	"Median (Nominal) Land Protrusion",
	"Minimum (Least) Land Protrusion",
    );

    my $land_str =
"               Density Level A            Density Level B           Density Level C
KEMET EIA       W    L    S     V1   V2    W    L    S    V1   V2    W    L    S    V1   V2
A     3216_18  1.35 2.20 0.62  6.02 2.80  1.23 1.80 0.82 4.92 2.30  1.13 1.42 0.98 4.06 2.04
B     3528_21  2.35 2.21 0.92  6.32 4.00  2.23 1.80 1.12 5.22 3.50  2.13 1.42 1.28 4.36 3.24
C     6032_25  2.35 2.77 2.37  8.92 4.50  2.23 2.37 2.57 7.82 4.00  2.13 1.99 2.73 6.96 3.74
D     7343_31  2.55 2.77 3.67 10.22 5.60  2.43 2.37 3.87 9.12 5.10  2.33 1.99 4.03 8.26 4.84
H     7360_20  4.25 2.77 3.67 10.22 7.30  4.13 2.37 3.87 9.12 6.80  4.03 1.99 4.03 8.26 6.54
L     6032_19  2.35 2.77 2.37  8.92 4.50  2.23 2.37 2.57 7.82 4.00  2.13 1.99 2.73 6.96 3.74
M     3528_15  2.35 2.20 0.92  6.32 4.00  2.23 1.80 1.12 5.22 3.50  2.13 1.42 1.28 4.36 3.24
Q     7343_12  2.55 2.77 3.67 10.22 5.60  2.43 2.37 3.87 9.12 5.10  2.33 1.99 4.03 8.26 4.84
T     3528_12  2.35 2.20 0.92  6.32 4.00  2.23 1.80 1.12 5.22 3.50  2.13 1.42 1.28 4.36 3.24
U     6032_15  2.35 2.77 2.37  8.92 4.50  2.23 2.37 2.57 7.82 4.00  2.13 1.99 2.73 6.96 3.74
V     7343_20  2.55 2.77 3.67 10.22 5.60  2.43 2.37 3.87 9.12 5.10  2.33 1.99 4.03 8.26 4.84
W     7343_15  2.55 2.77 3.67 10.22 5.60  2.43 2.37 3.87 9.12 5.10  2.33 1.99 4.03 8.26 4.84
X     7343_43  2.55 2.77 3.67 10.22 5.60  2.43 2.37 3.87 9.12 5.10  2.33 1.99 4.03 8.26 4.84
Y     7343_40  2.55 2.77 3.67 10.22 5.60  2.43 2.37 3.87 9.12 5.10  2.33 1.99 4.03 8.26 4.84
";
    my @land;
    for my $str (split(/\n/, $land_str)) {
	my @fld = split(/\s+/, $str);
	push @land, [ @fld ];
    }
    shift @land; shift @land; # skip the headers

    if (@dim != @land) {
	die("\@dim != \@land");
    }
    for (my $ix = 0; $ix < @dim; $ix++) {
	my $case = ${$dim[$ix]}[0];
	my $eiaf = ${$dim[$ix]}[1];
	my $eia  = $eiaf; $eia =~ s/_.*//;
	my $L    = ${$dim[$ix]}[2];
	my $W    = ${$dim[$ix]}[3];
	my $B    = ${$dim[$ix]}[7];
	#print "$case $eia $L $W $B\n";
	for (my $jx = 0; $jx < 3; $jx++) {
	    my $dens = $density[$jx];

	    my $lc = ${$land[$ix]}[0];
	    if ($lc ne $case) { warn("\$lc ($lc) ne \$case ($case)"); }
	    #my $le = ${$land[$ix]}[1];
	    #if ($le ne $eia ) { warn("\$le ($le) ne \$eia ($eia)"); } # the eia codes differs after the "_"

	    my $lx = 2 + 5 * $jx;
	    my $pw   = ${$land[$ix]}[$lx + 0];
	    my $pl   = ${$land[$ix]}[$lx + 1];
	    my $ps   = ${$land[$ix]}[$lx + 2];
	    my $pv1  = ${$land[$ix]}[$lx + 3];
	    my $pv2  = ${$land[$ix]}[$lx + 4];
	    #print("  $dens $pw $pl $ps $pv1 $pv2\n");

	    element_start("kemet_${case}_$dens.fp",
			  "# Kemet series T520 size $case/$eiaf capacitor with " . $dens_txt[$jx] . "\n# $doc\n");
	    my $s = ($ps + $pl) / 2;
	    pad(-$s, 0, $pl, $pw, "cathode");
	    pad( $s, 0, $pl, $pw, "anode");
	    pr("\n");
	    pr("# Body\n");
	    silk_crect([0,0], [$L,$W], 0);
	    silk_width(0.1);
	    pr("# Courtyard\n");
	    silk_crect([0,0], [$pv1,$pv2], 0);
	    silk_width(0.32);
	    pr("# + side marking\n");
	    my $polx = 0.3 * $L;
	    #my $b = 2 * $poly - 0.32 - 2*0.13;
	    my $b = 0.5;
	    my $poly = $b/2 + 0.3;
	    #my $poly = $W/4;
	    silk_cross($polx, 0, $b, 0.13);
	    silk_start($polx, $W/2);
	    silk_line( $polx, $poly);
	    silk_start($polx, -$W/2);
	    silk_line( $polx, -$poly);

	    element_stop();
	}
    }
}
#gen_kemet_t520();

sub gen_panasonic_oscon_smd() {
    my $doc = 'http://eu.industrial.panasonic.com/sites/default/pidseu/files/downloads/files/id_oscon1309_e.pdf';

#    my @sizes = (
#	[ qw/A5 4.0 5.4 4.3 4.3 5.0 0.7 1.0/ ],
#    );

    my $dim_str =
# D dia, L height,
# W widht of plastic base, H length of plastics, // cathode: wide side of plastics
# C leads end to end dist., R lead width, P gap between leads
"Case   D    L    W    H    C    R   P
A5    4.0  5.4  4.3  4.3  5.0  0.7 1.0
B45   5.0  4.4  5.3  5.3  6.0  0.7 1.4
B6    5.0  5.9  5.3  5.3  6.0  0.7 1.4
C5    6.3  4.9  6.6  6.6  7.3  0.7 2.1
C55   6.3  5.4  6.6  6.6  7.3  0.7 2.1
C6    6.3  5.9  6.6  6.6  7.3  0.7 2.1
C10   6.3  9.9  6.6  6.6  7.3  0.7 2.1
E7    8.0  6.9  8.3  8.3  9.0  0.7 3.2
E12   8.0 11.9  8.3  8.3  9.0  1.0 3.2
F8   10.0  7.9 10.3 10.3 11.0  0.7 4.6
F12  10.0 12.6 10.3 10.3 11.0  1.0 4.6
";
    my @dim;
    for my $str (split(/\n/, $dim_str)) {
	my @fld = split(/\s+/, $str);
	if ($fld[3] ne "W") {
	    my $shrt = (5.8 / 10.3) * $fld[3]; # guess short width of plastics.
	    $shrt = int($shrt * 10 + 0.5) / 10;
	    push @fld, $shrt;
	}
	push @dim, [ @fld ];
    }
    shift @dim; # skip the header

    # http://industrial.panasonic.com/lecs/www-data/pdf/AAB8000/AAB8000PE66.pdf
    my $land_str =
# a gap between pads, b total len pad end to pad end, c pad height
"Case  a    b   c
A5   1.0  6.2 1.6
B45  1.4  7.4 1.6
B6   1.4  7.4 1.6
C5   2.1  9.1 1.6
C55  2.1  9.1 1.6
C6   2.1  9.1 1.6
C10  2.1  9.1 1.6
E7   2.8 11.1 1.9
E12  2.8 11.1 1.9
F8   4.3 13.1 1.9
F12  4.3 13.1 1.9
";
    my @land;
    for my $str (split(/\n/, $land_str)) {
	my @fld = split(/\s+/, $str);
	push @land, [ @fld ];
    }
    shift @land; # skip the header

    if (@dim != @land) { die("\@dim != \@land"); }

    my %done;
    for (my $ix = 0; $ix < @dim; $ix++) {
	my $case = $dim[$ix][0];
	my $ltr = substr($case,0,1);
	if ($done{$ltr}) { next; }
	$done{$ltr} = 1;
	if ($case ne $land[$ix][0]) { die("$case ne $land[$ix][0]"); }

	my $D    = $dim[$ix][1];
	my $W    = $dim[$ix][3];
	my $H    = $dim[$ix][4];
	my $shrt = $dim[$ix][8];

	my $a    = $land[$ix][1];
	my $b    = $land[$ix][2];
	my $c    = $land[$ix][3];

	my $px   = ($b + $a) / 4;
	my $pw   = ($b - $a) / 2;
	my $ph   = $c;

	element_start("panasonic_oscon_smb_${ltr}.fp",
"# Panasonic Alumininum Capacitors, smd parts, size code $ltr (+possible number)
# $doc
");
	pad(-$px, 0, $pw, $ph, "cathode");
	pad( $px, 0, $pw, $ph, "anode");
	pr("\n");
	pr("# Body\n");
	my $bw = ($W - $shrt)/2; # bewel len
	#silk_width(0.18);
	silk_circle([0,0], $D/2);
	#silk_width(0.32);
	silk_start(-$H/2, -$W/2);
	silk_rline(0, $W);
	silk_rline($H-$bw,0);
	silk_rline($bw, -$bw);
	silk_rline(0, -$shrt);
	silk_rline(-$bw, -$bw);
	silk_rline(-$H+$bw,0);
	pr("# + side marking\n");
	silk_circle_segment([0,0], $D/2, 0.7*$D/2, 0);

	element_stop();

    }
}
#gen_panasonic_oscon_smd();

sub gen_bi_hm78d() {
    my $drill = 0.9;
    my $cu_dia = int(10 * $drill * 1.7 + 0.5) / 10;
    my $doc1 = "http/www.ttelectronicsmagnetics.com/pdf/datasheets/hm78d.pdf";
    my $doc2 = "https/www1.elfa.se/data1/wwwroot/assets/datasheets/hm78_eng_tds.pdf";

    my $hx = 0.5;  # extra width to make it easier to handsolder
    my $hy = 2;    # extra stickout to make it easier to handsolder
    for my $rr (@radi) {
	my $radi = 0;
	{
	    element_start("bi_hm78d_1210$rr.fp", "# $doc1\n# $doc2\n");
	    my @dim = (2, 4.2, 5.5, 4.5);
	    my $px = $dim[0] + $hx;
	    my $py = $dim[1] + $hy;
	    my $x = ($dim[2]+$hx - $px)/2;
	    my $y = ($dim[3] + $py)/2;
	    if ($rr) { $radi = $px / 4; }
	    pad( $x, -$y, $px, $py, "", "", $radi);
	    pad(-$x, -$y, $px, $py, "", "", $radi);
	    pad(-$x,  $y, $px, $py, "", "", $radi);
	    pad( $x,  $y, $px, $py, "", "", $radi);
	    pr("\n");
	    silk_crect([0,0], [12.5, 12.5], 0);
	    element_stop();
	}

	{
	    my @arr = (
		[ qw/128 12.5 12.5 8.05 5.0 5.0 3.5  1.5  4.2 5.5 4.5 2.0 12.8 4.2 4.5 2.0 4.2 5.5 4.5/ ],
		[ qw/755  7.7  7.7  4.8 3.9 2.7 1.55 0.72 2.2 2.8 3.1 1.0 7.5  2.2 3.1 1.0 2.2 2.8 3.1/ ],
	    );

	    for my $r (@arr) {
		my @dim = @$r;
		element_start("bi_hm78d_$dim[0]$rr.fp", "# $doc1\n# $doc2\n");
		my $px = $dim[11] + $hx;
		my $py = $dim[ 8] + $hy;
		my $x = ($dim[ 9]+$hx - $px)/2;
		my $y = ($dim[10] + $py)/2;
		if ($rr) { $radi = $px / 4; }
		pad( $x, -$y, $px, $py, "", "", $radi);
		pad(-$x, -$y, $px, $py, "", "", $radi);
		pad(-$x,  $y, $px, $py, "", "", $radi);
		pad( $x,  $y, $px, $py, "", "", $radi);
		pr("\n");
		silk_crect([0,0], [$dim[1], $dim[1]], 0);
		element_stop();
	    }
	}
    }
}
#gen_bi_hm78d();

sub gen_nexperia_smd($) {
    my $paste_as_outline = shift;
    my $prefix = "nexperia_";
    my $doc_prefix = "http://assets.nexperia.com/documents/outline-drawing";
    # I'm skipping the wave soldering footprints
    my @arr = ();
    my @tmp = ();
    my ($py, $px, $wx, $wy, $sx, $sy, $D, $E, $wx2, $sx2, $He, $bp, $top, $Lp, $x2, $x3, $y2, $y3);
    my $test;

    push @arr, [   [ "SOD123F" ],
		   [   [ "lr", 0.18,  -1.3, 0.8,  2.6, 0.0,  0.0, -1.60,  -2.6, 0.0,  0.0, 1.60 ],
		       [ "lr", 0.18,  -0.5, 0.8,  0, -1.6 ],
		   ],
		   [   [ 1,  -1.4, 0, 1.2, 1.2, "", "", 0,  ],
		       [ 2,   1.4, 0, 1.2, 1.2, "", "", 0,  ],
		   ],
		   [   [ 1,  -1.4, 0, 1.1, 1.1, "", "paste", 0, 0.1 ],
		       [ 2,   1.4, 0, 1.1, 1.1, "", "paste", 0, 0.1 ],
		   ],
	       ];

    push @arr, [   [ "SOD123W", "CFP3" ],
		   [   [ "lr", 0.18,  -1.3, 0.8,  2.6, 0.0,  0.0, -1.60,  -2.6, 0.0,  0.0, 1.60 ],
		       [ "lr", 0.18,  -0.5, 0.8,  0, -1.6 ],
		   ],
		   [   [ 1,  -1.4, 0, 1.2, 1.2, "", "", 0,  ],
		       [ 2,   1.4, 0, 1.2, 1.2, "", "", 0,  ],
		   ],
		   [   [ 1,  -1.4, 0, 1.1, 1.1, "", "paste", 0, 0.1 ],
		       [ 2,   1.4, 0, 1.1, 1.1, "", "paste", 0, 0.1 ],
		   ],
	       ];

    $px = 4.4/2; $py = 0/2;    $wx = 1.40;  $wy = 2.10;
    $D  = 3.8;   $E  = 2.50;   $sx = 1.20;  $sy = 1.90;
    push @arr, [   [ "SOD128", "CFP5" ],
		   [   [ "lr", 0.18,  -$D/2,$E/2,  $D,0,  0,-$E,  -$D,0,  0,$E, ],
		       [ "lr", 0.12,  -0.6*$D/2,$E/2,  0,-$E, ],
		   ],
		   [   [ 1,  -$px,     0,  $wx, $wy, "", "", 0,  ],
		       [ 2,   $px,     0,  $wx, $wy, "", "", 0,  ],
		   ],
		   [   [ 1,  -$px,     0,  $sx, $sy, "", "paste", 0,  ],
		       [ 2,   $px,     0,  $sx, $sy, "", "paste", 0,  ],
		   ],
	       ];

    $px = 2.2/2; $py = 0/2;    $wx = 0.60;  $wy = 0.60;
    $D  = 1.7;   $E  = 1.25;   $sx = 0.50;  $sy = 0.50;
    push @arr, [   [ "SOD323", "SC-76" ],
		   [   [ "lr", 0.18,  -$D/2,$E/2,  $D,0,  0,-$E,  -$D,0,  0,$E, ],
		       [ "lr", 0.12,  -0.6*$D/2,$E/2,  0,-$E, ],
		   ],
		   [   [ 1,  -$px,     0,  $wx, $wy, "", "", 0,  ],
		       [ 2,   $px,     0,  $wx, $wy, "", "", 0,  ],
		   ],
		   [   [ 1,  -$px,     0,  $sx, $sy, "", "paste", 0,  ],
		       [ 2,   $px,     0,  $sx, $sy, "", "paste", 0,  ],
		   ],
	       ];

    $px = 2.2/2; $py = 0/2;    $wx = 0.60;  $wy = 0.60;
    $D  = 1.7;   $E  = 1.25;   $sx = 0.50;  $sy = 0.50;
    push @arr, [   [ "SOD323F", "SC-90" ], # TODO: same fp as SOD323
		   [   [ "lr", 0.18,  -$D/2,$E/2,  $D,0,  0,-$E,  -$D,0,  0,$E, ],
		       [ "lr", 0.12,  -0.6*$D/2,$E/2,  0,-$E, ],
		   ],
		   [   [ 1,  -$px,     0,  $wx, $wy, "", "", 0,  ],
		       [ 2,   $px,     0,  $wx, $wy, "", "", 0,  ],
		   ],
		   [   [ 1,  -$px,     0,  $sx, $sy, "", "paste", 0,  ],
		       [ 2,   $px,     0,  $sx, $sy, "", "paste", 0,  ],
		   ],
	       ];

    $px = 1.4/2; $py = 0/2;   $wx = 0.50;  $wy = 0.60;
    $D  = 1.2;   $E  = 0.8;   $sx = 0.40;  $sy = 0.50;
    push @arr, [   [ "SOD523", "SC-79" ],
		   [   [ "lr", 0.18,  -$D/2,$E/2,  $D,0,  0,-$E,  -$D,0,  0,$E, ],
		       [ "lr", 0.12,  -0.16,$E/2,  0,-$E, ],
		   ],
		   [   [ 1,  -$px,     0,  $wx, $wy, "", "", 0,  ],
		       [ 2,   $px,     0,  $wx, $wy, "", "", 0,  ],
		   ],
		   [   [ 1,  -$px,     0,  $sx, $sy, "", "paste", 0,  ],
		       [ 2,   $px,     0,  $sx, $sy, "", "paste", 0,  ],
		   ],
	       ];

    push @arr, [   [ "SOD882", "DFN1006-2" ],
		   [   [ "lr", 0.1,  -0.50, 0.30,  1.0, 0.0,  0.0, -0.60,  -1.0, 0.0,  0.0, 0.60 ],
		       [ "lr", 0.1,  -0.35, 0.25,  0.0, -0.50 ],
		   ],
		   [   [ 1,  -0.35, 0, 0.4, 0.7, "", "", 0.05, 0.05 ],
		       [ 2,   0.35, 0, 0.4, 0.7, "", "", 0.05, 0.05 ],
		   ],
		   [   [ 1,  -0.35, 0, 0.3, 0.6, "", "paste", 0, 0.05 ],
		       [ 2,   0.35, 0, 0.3, 0.6, "", "paste", 0, 0.05 ],
		   ],
	       ];

    push @arr, [   [ "SOD882D", "DFN1006D-2" ],
		   [   [ "lr", 0.1,  -0.50, 0.25,  1.0, 0.0,  0.0, -0.50,  -1.0, 0.0,  0.0, 0.50 ],
		       [ "lr", 0.1,  -0.35, 0.25,  0.0, -0.50 ],
		   ],
		   [   [ 1,  -0.4, 0, 0.5, 0.7, "", "", 0, 0.1 ],
		       [ 2,   0.4, 0, 0.5, 0.7, "", "", 0, 0.1 ],
		   ],
		   [   [ 1,  -0.35, 0, 0.3, 0.6, "", "paste", 0, 0.1 ],
		       [ 2,   0.35, 0, 0.3, 0.6, "", "paste", 0, 0.1 ],
		   ],
	       ];

    $px = 0.7/2; $py = 0.35/2;  $wx = 0.40;  $wy = 0.25;
    $D  = 0.6;   $E  = 1.0;     $sx = 0.30;  $sy = 0.25;
    push @arr, [   [ "SOD883", "DFN1006-3" ],
		   [   [ "lr", 0.10,  $E/2,-$D/2,  0,$D,  -$E,0,  0,-$D,  $E,0, ],
		       [ "lr", 0.10,  -0.6*$E/2,$D/2,  0,-$D, ],
		   ],
		   [   [ 1,  -$px,  -$py,  $wx, $wy, "", "", 0.05, ],
		       [ 2,  -$px,   $py,  $wx, $wy, "", "", 0.05, ],
		       [ 3,   $px,     0,  $wx, 0.7, "", "", 0.05, ],
		   ],
		   [   [ 1,  -$px,  -$py,  $sx, $sy, "", "paste", 0.05, ],
		       [ 2,  -$px,   $py,  $sx, $sy, "", "paste", 0.05, ],
		       [ 3,   $px,     0,  0.3, 0.6, "", "paste", 0, ],
		   ],
	       ];

    # same fp as the above
    $px = 0.7/2; $py = 0.35/2;  $wx = 0.40;  $wy = 0.25;
    $D  = 0.6;   $E  = 1.0;     $sx = 0.30;  $sy = 0.25;
    push @arr, [   [ "SOD883B", "DFN1006B-3" ],
		   [   [ "lr", 0.10,  $E/2,-$D/2,  0,$D,  -$E,0,  0,-$D,  $E,0, ],
		       [ "lr", 0.10,  -0.6*$E/2,$D/2,  0,-$D, ],
		   ],
		   [   [ 1,  -$px,  -$py,  $wx, $wy, "", "", 0.05, ],
		       [ 2,  -$px,   $py,  $wx, $wy, "", "", 0.05, ],
		       [ 3,   $px,     0,  $wx, 0.7, "", "", 0.05, ],
		   ],
		   [   [ 1,  -$px,  -$py,  $sx, $sy, "", "paste", 0.05, ],
		       [ 2,  -$px,   $py,  $sx, $sy, "", "paste", 0.05, ],
		       [ 3,   $px,     0,  0.3, 0.6, "", "paste", 0, ],
		   ],
	       ];

    push @arr, [   [ "SOD962", "DSN0603-2" ],
		   [   [ "lr", 0.05,  -0.30, 0.15,  0.6, 0.0,  0.0, -0.30,  -0.6, 0.0,  0.0, 0.30 ],
		       [ "lr", 0.03,  -0.20, 0.15,  0.0, -0.30 ],
		   ],
		   [   [ 1,  -0.2, 0, 0.2, 0.28, "", "", 0, ],
		       [ 2,   0.2, 0, 0.2, 0.28, "", "", 0, ],
		   ],
		   [   [ 1,  -0.2, 0, 0.256, 0.256, "", "paste", 0.128, ],
		       [ 2,   0.2, 0, 0.256, 0.256, "", "paste", 0.128, ],
		   ],
	       ];
#    $test = $arr[$#arr];

    push @arr, [   [ "SOD1608", "DFN1608D-2" ],
		   [   [ "lr", 0.18,  -0.8, 0.4,  1.6, 0.0,  0.0, -0.80,  -1.6, 0.0,  0.0, 0.80 ],
		       [ "lr", 0.12,  -0.60, 0.4,  0.0, -0.80 ],
		   ],
		   [   [ 1,  -1.9/2 + 1.05/2, 0, 1.05, 0.8, "", "", 0, 0.05 ],
		       [ 2,   1.9/2 - 0.65/2, 0, 0.65, 0.8, "", "", 0, 0.05 ],
		   ],
		   [   [ 1,  -1.9/2 + 1.05/2, 0, 0.95, 0.7, "", "paste", 0, 0.05 ],
		       [ 2,   1.9/2 - 0.65/2, 0, 0.55, 0.7, "", "paste", 0, 0.05 ],
		   ],
	       ];

    $px = 1.9/2; $py = 2.0/2;  $wx = 0.6;  $wy = 0.7;
    $D  = 2.90;  $E  = 1.3;    $sx = 0.5;  $sy = 0.6;
    push @arr, [   [ "SOT23", "TO-236AB", ],
		   [   [ "lr", 0.10,  -$D/2,$E/2,  $D,0,  0,-$E,  -$D,0,  0,$E, ],
		       [ "lr", 0.05,  $px-$wx/2,-$E/2,  $wx/2,0.2,  $wx/2,-0.2, ],
		   ],
		   [   [ 1,   $px,  -$py,  $wx,  $wy, "", "", 0, ],
		       [ 2,  -$px,  -$py,  $wx,  $wy, "", "", 0, ],
		       [ 3,     0,   $py,  $wx,  $wy, "", "", 0, ],
		   ],
		   [   [ 1,   $px,  -$py,  $sx,  $sy, "", "paste", 0, ],
		       [ 2,  -$px,  -$py,  $sx,  $sy, "", "paste", 0, ],
		       [ 3,     0,   $py,  $sx,  $sy, "", "paste", 0, ],
		   ],
	       ];

    $px = 2.40/2; $py = 4.6/2-1.1/2; $wx = 0.70;  $wy = 1.10;
    $D  = 4.5;    $E  = 2.5;         $sx = 0.60;  $sy = 1.00;
    $He = 4; $Lp = 1; $bp = 1.6; $top = $He - $E - $Lp;
    push @arr, [   [ "SOT89", "TO-243", "SC-62"], # TODO: weird pin numbering
		   [   [ "lr", 0.18,  -$D/2,$He/2-$Lp, $D,0, 0,-$E, -($D-$bp)/2,0,
			 0,-$top/2, -$top/2,-$top/2, -$bp+$top,0, -$top/2,$top/2, 0,$top/2, -($D-$bp)/2,0, 0,$E, ],
		       [ "lr", 0.12,  $px+$wx/2,$He/2-$Lp,  -$wx/2,-0.2,  -$wx/2,0.2, ],
		   ],
		   [   [ 1,   $px,   $py,   $wx, $wy, "", "", 0,  ],
		       [ 2,     0, (4.6/2+0.5)/2, $wx, 4.6/2-0.5, "", "", 0,  ],
		       [ 2,     0, -(4.6/2-0.5)/2, 2, 4.6/2+0.5, "", "", 0,  ],
		       [ 3,  -$px,   $py,   $wx, $wy, "", "", 0,  ],
		   ],
		   [   [ 1,   $px,   $py,  $sx, $sy , "", "paste", 0,  ],
		       [ 2,     0,   $py,  $sx, $sy , "", "paste", 0,  ],
		       [ 2,     0,  -0.6,  1.2, 1.2 , "", "paste", 0,  ],
		       [ 2,     0,  -1.4-0.85/2,  1.9, 0.85, "", "paste", 0,  ],
		       [ 3,  -$px,   $py,  $sx, $sy , "", "paste", 0,  ],
		   ],
	       ];

    push @arr, [   [ "SOT143B" ],
		   [   [ "lr", 0.25,  -1.5, 0.7,  3.0, 0,  0, -1.4,  -3.0, 0,  0, 1.4 ],
		       [ "lr", 0.12,  -1.25, 0.7,  0.5, -0.3,  0.5, 0.3 ],
		   ],
		   [   [ 1,  -0.75,  1.00,  1.00, 0.70, "", "", 0, ],
		       [ 2,   0.95,  1.00,  0.60, 0.70, "", "", 0, ],
		       [ 3,   0.95, -1.00,  0.60, 0.70, "", "", 0, ],
		       [ 4,  -0.95, -1.00,  0.60, 0.70, "", "", 0, ],
		   ],
		   [   [ 1,  -0.75,  1.00,  0.90, 0.60, "", "paste", 0, ],
		       [ 2,   0.95,  1.00,  0.50, 0.60, "", "paste", 0, ],
		       [ 3,   0.95, -1.00,  0.50, 0.60, "", "paste", 0, ],
		       [ 4,  -0.95, -1.00,  0.50, 0.60, "", "paste", 0, ],
		   ],
	       ];

    $px = 2.3;  $py = 6.1/2; $wx = 1.3;  $wy = 1.3;
    $D  = 6.50; $E  = 3.5;   $sx = 1.2;  $sy = 1.2;
    $y2 = 0.25; $y3 = $y2 + 0.55 + 0.25/2;
    $x2 = (3.5/2+0.3/2)/2; $x3 = (3.5-0.3)/2;
    push @arr, [   [ "SOT223", "SC-73", ],
		   [   [ "lr", 0.10,  -$D/2,$E/2,  $D,0,  0,-$E,  -$D,0,  0,$E, ],
		       [ "lr", 0.05,  -$px-$wx/2,$E/2,  $wx/2,-0.2,  $wx/2,0.2, ],
		   ],
		   [   [ 1,  -$px,   $py,  $wx,  $wy, "", "", 0, ],
		       [ 2,     0,   $py,  $wx,  $wy, "", "", 0, ],
		       [ 3,   $px,   $py,  $wx,  $wy, "", "", 0, ],
		       [ 4,     0,  -$py,  3.6,  $wy, "", "", 0, ],

		   ],
		   [   [ 1,  -$px,   $py,  $sx,  $sy, "", "paste", 0, ],
		       [ 2,     0,   $py,  $sx,  $sy, "", "paste", 0, ],
		       [ 3,   $px,   $py,  $sx,  $sy, "", "paste", 0, ],
		       [ 4,  -$x2,  -$py,  $x3,  $sy, "", "paste", 0, ],
		       [ 4,   $x2,  -$py,  $x3,  $sy, "", "paste", 0, ],
		   ],
	       ];

    $px = 1.85/2; $py = 1.3/2;  $wx = 0.55;  $wy = 0.6;
    $D  = 2.0;    $E  = 1.25;   $sx = 0.55;  $sy = 0.5;
    push @arr, [   [ "SOT323", "SC-70" ],
		   [   [ "lr", 0.18,  $E/2,$D/2,   0,-$D,  -$E,0,  0,$D,  $E,0 ],
		       [ "lr", 0.12,  $E/2,$py+$wy/2,  -0.2, -$wy/2,  0.2,-$wy/2 ],
		   ],
		   [   [ 1,   $px,   $py,  $wx, $wy, "", "", 0,  ],
		       [ 2,   $px,  -$py,  $wx, $wy, "", "", 0,  ],
		       [ 3,  -$px,     0,  $wx, $wy, "", "", 0,  ],
		   ],
		   [   [ 1,   $px,   $py,  $sx, $sy, "", "paste", 0,  ],
		       [ 2,   $px,  -$py,  $sx, $sy, "", "paste", 0,  ],
		       [ 3,  -$px,     0,  $sx, $sy, "", "paste", 0,  ],
		   ],
	       ];

    $py = 1.5/2;
    $px = 1.8/2;
    push @arr, [   [ "SOT353", "TSSOP5" ],
		   [   [ "lr", 0.18,   0.675,  1.0,  0.0, -2.0,  -1.25, 0.0,  0.0,  2.0,  1.25, 0 ],
		       [ "lr", 0.10,   0.175,  1.0,  0.5, -0.5 ],
		   ],
		   [   [ 1,   $px,   $py,  0.60, 0.60, "", "", 0, ],
		       [ 2,   $px,     0,  0.60, 0.40, "", "", 0, ],
		       [ 3,   $px,  -$py,  0.60, 0.60, "", "", 0, ],
		       [ 4,  -$px,  -$py,  0.60, 0.60, "", "", 0, ],
		       [ 5,  -$px,   $py,  0.60, 0.60, "", "", 0, ],
		   ],
		   [   [ 1,   $px,   $py,  0.50, 0.50, "", "paste", 0, ],
		       [ 2,   $px,     0,  0.50, 0.40, "", "paste", 0, ],
		       [ 3,   $px,  -$py,  0.50, 0.50, "", "paste", 0, ],
		       [ 4,  -$px,  -$py,  0.50, 0.50, "", "paste", 0, ],
		       [ 5,  -$px,   $py,  0.50, 0.50, "", "paste", 0, ],
		   ],
	       ];

    $px = 1.50/2; $py = 1.8/2;   $wx = 0.60;  $wy = 0.60;
    $D  = 2.0;    $E  = 1.25;    $sx = 0.50;  $sy = 0.50;
    $y2 = 0.4; $y3 = 0.4;
    push @arr, [   [ "SOT363", "TSSOP6" ],
		   [   [ "lr", 0.18,  -$E/2,-$D/2,   0,$D,  $E,0,  0,-$D, -$E,0 ],
		       [ "lr", 0.12,  -$E/2,-$py-$wy/2,  0.2,$wy/2,  -0.2,$wy/2 ],
		   ],
		   [   [ 1,  -$px,  -$py,  $wx, $wy, "", "", 0,  ],
		       [ 2,  -$px,     0,  $wx, $y2, "", "", 0,  ],
		       [ 3,  -$px,   $py,  $wx, $wy, "", "", 0,  ],
		       [ 4,   $px,   $py,  $wx, $wy, "", "", 0,  ],
		       [ 5,   $px,     0,  $wx, $y2, "", "", 0,  ],
		       [ 6,   $px,  -$py,  $wx, $wy, "", "", 0,  ],
		   ],
		   [   [ 1,  -$px,  -$py,  $wx, $wy, "", "paste", 0,  ],
		       [ 2,  -$px,     0,  $wx, $y3, "", "paste", 0,  ],
		       [ 3,  -$px,   $py,  $wx, $wy, "", "paste", 0,  ],
		       [ 4,   $px,   $py,  $wx, $wy, "", "paste", 0,  ],
		       [ 5,   $px,     0,  $wx, $y3, "", "paste", 0,  ],
		       [ 6,   $px,  -$py,  $wx, $wy, "", "paste", 0,  ],
		   ],
	       ];

    $px = 1.3/2; $py = 1.0/2;   $wx = 0.6;  $wy = 0.5;
    $D  = 1.6;   $E  = 0.8;
    push @arr, [   [ "SOT416", "SC-75" ],
		   [   [ "lr", 0.18,  $E/2,$D/2,   0,-$D,  -$E,0,  0,$D,  $E,0 ],
		       [ "lr", 0.12,  $E/2,$py+$wy/2,  -0.2, -$wy/2,  0.2,-$wy/2 ],
		   ],
		   [   [ 1,   $px,   $py,  $wx, $wy, "", "", 0,  ],
		       [ 2,   $px,  -$py,  $wx, $wy, "", "", 0,  ],
		       [ 3,  -$px,     0,  $wx, $wy, "", "", 0,  ],
		   ],
		   [   [ 1,   $px,   $py,  $wx, $wy, "", "paste", 0,  ],
		       [ 2,   $px,  -$py,  $wx, $wy, "", "paste", 0,  ],
		       [ 3,  -$px,     0,  $wx, $wy, "", "paste", 0,  ],
		   ],
	       ];

    $px = 4.57/2; $py = 6-2.4/2;   $wx = 1.4;  $wy = 2.4;
    $D  = 6.10;   $E  = 6.60;
    {
	my $top = 10 - $D - 2.75;
	my $b2 = 5.24;
	my $pc = 1.15 - 5.75/2;
	my $r = [   [ "SOT428", "DPAK" ],
		    [   [ "lr", 0.18,
			  -$E/2,$D/2,  $E,0,  0,-$D,  -($E-$b2)/2,0,  0,-$top,
			  -$b2,0,  0,$top,  -($E-$b2)/2,0, 0,$D
		      ],

		    ],
		    [   [ 1,  -$px,  $py,  $wx,  $wy, "", "", 0, 0.05 ],
			[ 2,     0,  $pc,  5.9, 5.75, "", "", 0, 0.05 ],
			[ 3,   $px,  $py,  $wx,  $wy, "", "", 0, 0.05 ],
		    ],
		];
	$sx = 1.3;  $sy = 1;
	my $s = [
	    [ 1,   -$px, $py+0.65,  $sx, $sy, "", "paste", 0,  ],
	    [ 1,   -$px, $py-0.65,  $sx, $sy, "", "paste", 0,  ],
	    [ 3,    $px, $py+0.65,  $sx, $sy, "", "paste", 0,  ],
	    [ 3,    $px, $py-0.65,  $sx, $sy, "", "paste", 0,  ],
	];
	$sx = 1.8;  $sy = 1;
	my $dy = 5.65/2 - $sy/2;
	my @yy = ($pc + $dy, $pc, $pc - $dy);
	my $dx = 5.8/2 - $sx/2;
	my @xx = (-$dx, 0, $dx);
	for $py (@yy) {
	    for $px (@xx) {
		push @$s, [ 2,  $px, $py,  $sx, $sy, "", "paste", 0,  ];
	    }
	}

	push @$r, $s;
	push @arr, $r;
    }

    $px = 2.40/2; $py = 0.95;    $wx = 0.80;  $wy = 0.55;
    $D  = 2.9;    $E  = 1.5;     $sx = 0.70;  $sy = 0.45;
    push @arr, [   [ "SOT457", "TSOP6" ],
		   [   [ "lr", 0.18,  $E/2,$D/2,   0,-$D,  -$E,0,  0,$D,  $E,0 ],
		       [ "lr", 0.12,  $E/2,$py+$wy/2,  -0.2, -$wy/2,  0.2,-$wy/2 ],
		   ],
		   [   [ 1,   $px,   $py,  $wx, $wy, "", "", 0,  ],
		       [ 2,   $px,     0,  $wx, $wy, "", "", 0,  ],
		       [ 3,   $px,  -$py,  $wx, $wy, "", "", 0,  ],
		       [ 4,  -$px,  -$py,  $wx, $wy, "", "", 0,  ],
		       [ 5,  -$px,     0,  $wx, $wy, "", "", 0,  ],
		       [ 6,  -$px,   $py,  $wx, $wy, "", "", 0,  ],
		   ],
		   [   [ 1,   $px,   $py,  $wx, $wy, "", "paste", 0,  ],
		       [ 2,   $px,     0,  $wx, $wy, "", "paste", 0,  ],
		       [ 3,   $px,  -$py,  $wx, $wy, "", "paste", 0,  ],
		       [ 4,  -$px,  -$py,  $wx, $wy, "", "paste", 0,  ],
		       [ 5,  -$px,     0,  $wx, $wy, "", "paste", 0,  ],
		       [ 6,  -$px,   $py,  $wx, $wy, "", "paste", 0,  ],
		   ],
	       ];

    $px = 1.65/2; $py = 1.0/2;   $wx = 0.55;  $wy = 0.55;
    $D  = 1.6;    $E  = 1.2;     $sx = 0.50;  $sy = 0.50;
    push @arr, [   [ "SOT663", ],
		   [   [ "lr", 0.18,  $E/2,$D/2,   0,-$D,  -$E,0,  0,$D,  $E,0 ],
		       [ "lr", 0.12,  $E/2,$py+$wy/2,  -0.2, -$wy/2,  0.2,-$wy/2 ],
		   ],
		   [   [ 1,   $px,   $py,  $wx, $wy, "", "", 0,  ],
		       [ 2,   $px,  -$py,  $wx, $wy, "", "", 0,  ],
		       [ 3,  -$px,     0,  $wx, $wy, "", "", 0,  ],
		   ],
		   [   [ 1,   $px,   $py,  $sx, $sy, "", "paste", 0,  ],
		       [ 2,   $px,  -$py,  $sx, $sy, "", "paste", 0,  ],
		       [ 3,  -$px,     0,  $sx, $sy, "", "paste", 0,  ],
		   ],
	       ];

    $px = 1.70/2; $py = 0.538;   $wx = 0.50;  $wy = 0.375;
    $D  = 1.6;    $E  = 1.2;     $sx = 0.45;  $sy = 0.325;
    push @arr, [   [ "SOT665", ],
		   [   [ "lr", 0.18,  $E/2,$D/2,   0,-$D,  -$E,0,  0,$D,  $E,0 ],
		       [ "lr", 0.12,  $E/2,$py+$wy/2,  -0.2, -$wy/2,  0.2,-$wy/2 ],
		   ],
		   [   [ 1,   $px,   $py,   $wx, $wy, "", "", 0,  ],
		       [ 2,   $px+0.075,     0,  0.65, 0.3, "", "", 0,  ],
		       [ 3,   $px,  -$py,   $wx, $wy, "", "", 0,  ],
		       [ 4,  -$px,  -0.5,   $wx, 0.5, "", "", 0,  ],
		       [ 5,  -$px,   0.5,   $wx, 0.5, "", "", 0,  ],
		   ],
		   [   [ 1,   $px,   $py,  $sx, $sy, "", "paste", 0,  ],
		       [ 2,   $px+0.075,     0,  0.6, 0.25, "", "paste", 0,  ],
		       [ 3,   $px,  -$py,  $sx, $sy, "", "paste", 0,  ],
		       [ 4,  -$px,  -0.5,  $sx, 0.45, "", "paste", 0,  ],
		       [ 5,  -$px,   0.5,  $sx, 0.45, "", "paste", 0,  ],
		   ],
	       ];

    $px = 1.70/2; $py = 0.538;   $wx = 0.50;  $wy = 0.375;
    $D  = 1.6;    $E  = 1.2;     $sx = 0.45;  $sy = 0.325;
    push @arr, [   [ "SOT666", ],
		   [   [ "lr", 0.18,  $E/2,$D/2,   0,-$D,  -$E,0,  0,$D,  $E,0 ],
		       [ "lr", 0.12,  $E/2,$py+$wy/2,  -0.2, -$wy/2,  0.2,-$wy/2 ],
		   ],
		   [   [ 1,   $px,   $py,   $wx, $wy, "", "", 0,  ],
		       [ 2,   $px+0.075,     0,  0.65, 0.3, "", "", 0,  ],
		       [ 3,   $px,  -$py,   $wx, $wy, "", "", 0,  ],
		       [ 4,  -$px,  -$py,   $wx, $wy, "", "", 0,  ],
		       [ 5,  -$px-0.075,     0,  0.65, 0.3, "", "", 0,  ],
		       [ 6,  -$px,   $py,   $wx, $wy, "", "", 0,  ],
		   ],
		   [   [ 1,   $px,   $py,  $sx, $sy, "", "paste", 0,  ],
		       [ 2,   $px+0.075,     0,  0.6, 0.25, "", "paste", 0,  ],
		       [ 3,   $px,  -$py,  $sx, $sy, "", "paste", 0,  ],
		       [ 4,  -$px,  -$py,  $sx, $sy, "", "paste", 0,  ],
		       [ 5,  -$px-0.075,     0,  0.6, 0.25, "", "paste", 0,  ],
		       [ 6,  -$px,   $py,  $sx, $sy, "", "paste", 0,  ],
		   ],
	       ];

    $px = 2.40/2; $py = 0.95;   $wx = 0.80;  $wy = 0.55;
    $D  = 2.9;    $E  = 1.5;    $sx = 0.70;  $sy = 0.45;
    push @arr, [   [ "SOT753", ],
		   [   [ "lr", 0.18,  $E/2,$D/2,   0,-$D,  -$E,0,  0,$D,  $E,0 ],
		       [ "lr", 0.12,  $E/2,$py+$wy/2,  -0.2, -$wy/2,  0.2,-$wy/2 ],
		   ],
		   [   [ 1,   $px,   $py,   $wx, $wy, "", "", 0,  ],
		       [ 2,   $px,     0,   $wx, $wy, "", "", 0,  ],
		       [ 3,   $px,  -$py,   $wx, $wy, "", "", 0,  ],
		       [ 4,  -$px,  -$py,   $wx, $wy, "", "", 0,  ],
		       [ 5,  -$px,     0,   $wx, $wy, "", "", 0,  ],
		       [ 6,  -$px,   $py,   $wx, $wy, "", "", 0,  ],
		   ],
		   [   [ 1,   $px,   $py,  $sx, $sy, "", "paste", 0,  ],
		       [ 2,   $px,     0,  $sx, $sy, "", "paste", 0,  ],
		       [ 3,   $px,  -$py,  $sx, $sy, "", "paste", 0,  ],
		       [ 4,  -$px,  -$py,  $sx, $sy, "", "paste", 0,  ],
		       [ 5,  -$px,     0,  $sx, $sy, "", "paste", 0,  ],
		       [ 6,  -$px,   $py,  $sx, $sy, "", "paste", 0,  ],
		   ],
	       ];

    $px = 0.675/2; $py = 0.5;   $wx = 0.325;  $wy = 0.270;
    $D  = 1.45;    $E  = 1.0;   $sx = 0.325;  $sy = 0.270;
    push @arr, [   [ "SOT886", ], # TODO: "XSON6", name clash with SOT891
		   [   [ "lr", 0.12,  $E/2,$D/2,   0,-$D,  -$E,0,  0,$D,  $E,0 ],
		       [ "lr", 0.10,  $E/2,$py+$wy/2,  -0.2, -$wy/2,  0.2,-$wy/2 ],
		   ],
		   [   [ 1,   $px,   $py,  $wx, $wy, "", "", 0, 0.05  ],
		       [ 2,   $px,     0,  $wx, $wy, "", "", 0, 0.05  ],
		       [ 3,   $px,  -$py,  $wx, $wy, "", "", 0, 0.05  ],
		       [ 4,  -$px,  -$py,  $wx, $wy, "", "", 0, 0.05  ],
		       [ 5,  -$px,     0,  $wx, $wy, "", "", 0, 0.05  ],
		       [ 6,  -$px,   $py,  $wx, $wy, "", "", 0, 0.05  ],
		   ],
		   [   [ 1,   $px,   $py,  $sx, $sy, "", "paste", 0, 0.05  ],
		       [ 2,   $px,     0,  $sx, $sy, "", "paste", 0, 0.05  ],
		       [ 3,   $px,  -$py,  $sx, $sy, "", "paste", 0, 0.05  ],
		       [ 4,  -$px,  -$py,  $sx, $sy, "", "paste", 0, 0.05  ],
		       [ 5,  -$px,     0,  $sx, $sy, "", "paste", 0, 0.05  ],
		       [ 6,  -$px,   $py,  $sx, $sy, "", "paste", 0, 0.05  ],
		   ],
	       ];

    $px = 0.35; $py = 0.7/2; $wx = 0.25;  $wy = 0.50;
    $D  = 1.00; $E  = 1.0;   $sx = 0.25;  $sy = 0.50;
    push @arr, [   [ "SOT891", ], # TODO: "XSON6", name clash with SOT886
		   [   [ "lr", 0.10,  -$D/2,$E/2,   $D,0,  0,-$E,  -$D,0,  0,$E, ],
		       [ "lr", 0.05,  -$px-$wx/2,$E/2,  $wx/2,-0.2,  $wx/2,0.2, ],
		   ],
		   [   [ 1,  -$px,   $py,  $wx, $wy, "", "", 0, 0.05  ],
		       [ 2,     0,   $py,  $wx, $wy, "", "", 0, 0.05  ],
		       [ 3,   $px,   $py,  $wx, $wy, "", "", 0, 0.05  ],
		       [ 4,   $px,  -$py,  $wx, $wy, "", "", 0, 0.05  ],
		       [ 5,     0,  -$py,  $wx, $wy, "", "", 0, 0.05  ],
		       [ 6,  -$px,  -$py,  $wx, $wy, "", "", 0, 0.05  ],
		   ],
		   [   [ 1,  -$px,   $py,  $wx, $wy, "", "paste", 0, 0.05  ],
		       [ 2,     0,   $py,  $wx, $wy, "", "paste", 0, 0.05  ],
		       [ 3,   $px,   $py,  $wx, $wy, "", "paste", 0, 0.05  ],
		       [ 4,   $px,  -$py,  $wx, $wy, "", "paste", 0, 0.05  ],
		       [ 5,     0,  -$py,  $wx, $wy, "", "paste", 0, 0.05  ],
		       [ 6,  -$px,  -$py,  $wx, $wy, "", "paste", 0, 0.05  ],
		   ],
	       ];

    $px = 1.3/2; $py = 1.05;  $wx = 0.4;  $wy = 0.5;
    $D  = 2.00;  $E  = 2.0;   $sx = 0.4;  $sy = 0.5;
    $y2 = 0.25; $y3 = $y2 + 0.55 + 0.25/2;
    push @arr, [   [ "SOT1061", ],
		   [   [ "lr", 0.10,  $D/2,-$E/2,  -$D,0,  0,$E,  $D,0,  0,-$E, ],
		       [ "lr", 0.05,  $px-$wx/2,-$E/2,  $wx/2,0.2,  $wx/2,-0.2, ],
		   ],
		   [   [ 1,   $px,  -$py,  $wx,  $wy, "", "", 0, 0.05  ],
		       [ 2,  -$px,  -$py,  $wx,  $wy, "", "", 0, 0.05  ],
		       [ 3,     0,   $y2,  1.6, 1.10, "", "", 0, 0.05  ],
		       [ 3,     0,   $y3,  0.4, 0.25, "", "", 0, 0.05  ],
		   ],
		   [   [ 1,   $px,  -$py,  $wx,  $wy, "", "paste", 0, 0.05  ],
		       [ 2,  -$px,  -$py,  $wx,  $wy, "", "paste", 0, 0.05  ],
		       [ 3,     0,   $y2,  1.6, 1.10, "", "paste", 0, 0.05  ],
		       [ 3,     0,   $y3,  0.4, 0.25, "", "paste", 0, 0.05  ],
		   ],
	       ];

    $px = 0.65; $py = 0.875; $wx = 0.35;  $wy = 0.30;
    $D  = 2.00; $E  = 2.0;   $sx = 0.35;  $sy = 0.30;
    $x2 = 0.49; $x3 = 0.72; $y3 = 1.05;
    push @arr, [   [ "SOT1118", "DFN2020-6" ],
		   [   [ "lr", 0.10,  -$D/2,$E/2,   $D,0,  0,-$E,  -$D,0,  0,$E, ],
		       [ "lr", 0.05,  -$px-$wx/2,$E/2,  $wx/2,-0.2,  $wx/2,0.2, ],
		   ],
		   [   [ 1,  -$px,   $py,  $wx, $wy, "", "", 0, 0.05  ],
		       [ 2,     0,   $py,  $wx, $wy, "", "", 0, 0.05  ],
		       [ 3,   $px,   $py,  $wx, $wy, "", "", 0, 0.05  ],
		       [ 4,   $px,  -$py,  $wx, $wy, "", "", 0, 0.05  ],
		       [ 5,     0,  -$py,  $wx, $wy, "", "", 0, 0.05  ],
		       [ 6,  -$px,  -$py,  $wx, $wy, "", "", 0, 0.05  ],
		       [ 7,  -$x2,     0,  $x3, $y3, "", "", 0, 0.05  ],
		       [ 8,   $x2,     0,  $x3, $y3, "", "", 0, 0.05  ],
		   ],
		   [   [ 1,  -$px,   $py,  $wx, $wy, "", "paste", 0, 0.05  ],
		       [ 2,     0,   $py,  $wx, $wy, "", "paste", 0, 0.05  ],
		       [ 3,   $px,   $py,  $wx, $wy, "", "paste", 0, 0.05  ],
		       [ 4,   $px,  -$py,  $wx, $wy, "", "paste", 0, 0.05  ],
		       [ 5,     0,  -$py,  $wx, $wy, "", "paste", 0, 0.05  ],
		       [ 6,  -$px,  -$py,  $wx, $wy, "", "paste", 0, 0.05  ],
		       [ 7,  -$x2,     0,  $x3, $y3, "", "paste", 0, 0.05  ],
		       [ 8,   $x2,     0,  $x3, $y3, "", "paste", 0, 0.05  ],
		   ],
	       ];

    $py = (1.25+0.3)/4;
    $px  = 0.5;
    push @arr, [   [ "SOT1176-1", "DFN2510A-10" ],
		   [   [ "lr", 0.18,  -1.25, 0.5,  2.5, 0,  0, -1,  -2.5, 0,  0, 1 ],
		       [ "lr", 0.10,  -1.25, 0.1,  0.4, 0.4 ],
		   ],
		   [   [  1,  -2*$px,  $py,  0.20, 0.475, "", "", 0, 0.05 ],
		       [  2,  -1*$px,  $py,  0.20, 0.475, "", "", 0, 0.05 ],
		       [  3,   0*$px,  $py,  0.20, 0.475, "", "", 0, 0.05 ],
		       [  4,   1*$px,  $py,  0.20, 0.475, "", "", 0, 0.05 ],
		       [  5,   2*$px,  $py,  0.20, 0.475, "", "", 0, 0.05 ],
		       [  6,   2*$px, -$py,  0.20, 0.475, "", "", 0, 0.05 ],
		       [  7,   1*$px, -$py,  0.20, 0.475, "", "", 0, 0.05 ],
		       [  8,   0*$px, -$py,  0.20, 0.475, "", "", 0, 0.05 ],
		       [  9,  -1*$px, -$py,  0.20, 0.475, "", "", 0, 0.05 ],
		       [ 10,  -2*$px, -$py,  0.20, 0.475, "", "", 0, 0.05 ],
		   ],
		   [   [  1,  -2*$px,  $py,  0.20, 0.475, "", "", 0, 0.05 ],
		       [  2,  -1*$px,  $py,  0.20, 0.475, "", "", 0, 0.05 ],
		       [  3,   0*$px,  $py,  0.20, 0.475, "", "", 0, 0.05 ],
		       [  4,   1*$px,  $py,  0.20, 0.475, "", "", 0, 0.05 ],
		       [  5,   2*$px,  $py,  0.20, 0.475, "", "", 0, 0.05 ],
		       [  6,   2*$px, -$py,  0.20, 0.475, "", "", 0, 0.05 ],
		       [  7,   1*$px, -$py,  0.20, 0.475, "", "", 0, 0.05 ],
		       [  8,   0*$px, -$py,  0.20, 0.475, "", "", 0, 0.05 ],
		       [  9,  -1*$px, -$py,  0.20, 0.475, "", "", 0, 0.05 ],
		       [ 10,  -2*$px, -$py,  0.20, 0.475, "", "", 0, 0.05 ],
		   ],
	       ];

    $py = 0.7;
    $px = 0.35;
    push @arr, [   [ "SOT1202", "XSON6" ],
		   [   [ "lr", 0.18,  -0.5, 0.5,  1, 0,  0, -1,  -1, 0,  0, 1 ],
		       [ "lr", 0.10,  -0.5, 0.1,  0.4, 0.4 ],
		   ],
		   [   [ 1,  -$px,   $py,  0.15, 0.5, "", "", 0, 0.05 ],
		       [ 2,     0,   $py,  0.15, 0.5, "", "", 0, 0.05 ],
		       [ 3,   $px,   $py,  0.15, 0.5, "", "", 0, 0.05 ],
		       [ 4,   $px,  -$py,  0.15, 0.5, "", "", 0, 0.05 ],
		       [ 5,     0,  -$py,  0.15, 0.5, "", "", 0, 0.05 ],
		       [ 6,  -$px,  -$py,  0.15, 0.5, "", "", 0, 0.05 ],

		   ],
		   [   [ 1,  -$px,   $py,  0.15, 0.5, "", "paste", 0, 0.05 ],
		       [ 2,     0,   $py,  0.15, 0.5, "", "paste", 0, 0.05 ],
		       [ 3,   $px,   $py,  0.15, 0.5, "", "paste", 0, 0.05 ],
		       [ 4,   $px,  -$py,  0.15, 0.5, "", "paste", 0, 0.05 ],
		       [ 5,     0,  -$py,  0.15, 0.5, "", "paste", 0, 0.05 ],
		       [ 6,  -$px,  -$py,  0.15, 0.5, "", "paste", 0, 0.05 ],

		   ],
	       ];


    $px = 1.27; $py = (3.85+2.7)/2; $wx = 0.70;     $wy = 3.85-2.7;
    $D  = 4.6;  $E  = 5.15;         $sx = $wx-0.05; $sy = $wy-0.05;
    @tmp = (  [ "SOT1205", "LFPAK56D", ],
	      [   [ "lr", 0.18,  -$E/2,$D/2, $E,0, 0,-$D, -$E,0, 0,$D, ],
		  [ "lr", 0.12, -1.5*$px-$wx/2,$D/2,  $wx/2,-0.4,  $wx/2,0.4, ],
	      ],
	  );
    $y2 = -(3.2+2.0)/2; $y3 = (3.2-2.0);
    $x2 = $px+$wx;
    push @tmp, [   [ 1, -1.5*$px,   $py,   $wx, $wy, "", "", 0,  ],
		   [ 2, -0.5*$px,   $py,   $wx, $wy, "", "", 0,  ],
		   [ 3,  0.5*$px,   $py,   $wx, $wy, "", "", 0,  ],
		   [ 4,  1.5*$px,   $py,   $wx, $wy, "", "", 0,  ],
		   [ 5,  1.5*$px,   $y2,   $wx, $y3, "", "", 0,  ],
		   [ 5,  0.5*$px,   $y2,   $wx, $y3, "", "", 0,  ],
		   [ 5,  $px, 0.05,  $x2, 4.1, "", "", 0,  ],
		   [ 6, -0.5*$px,   $y2,   $wx, $y3, "", "", 0,  ],
		   [ 6, -1.5*$px,   $y2,   $wx, $y3, "", "", 0,  ],
		   [ 6, -$px, 0.05,  $x2, 4.1, "", "", 0,  ],
	       ];
    $y2 = -(3.175+1.275)/2; $y3 = (3.175-1.275);
    push @tmp, [   [ 1, -1.5*$px,   $py,   $sx, $sy, "", "paste", 0,  ],
		   [ 2, -0.5*$px,   $py,   $sx, $sy, "", "paste", 0,  ],
		   [ 3,  0.5*$px,   $py,   $sx, $sy, "", "paste", 0,  ],
		   [ 4,  1.5*$px,   $py,   $sx, $sy, "", "paste", 0,  ],
		   [ 5,  1.5*$px,   $y2,   $sx, $y3, "", "paste", 0,  ],
		   [ 5,  0.5*$px,   $y2,   $sx, $y3, "", "paste", 0,  ],
		   [ 5,  $px, 1.375, 1.1, 1.0, "", "paste", 0,  ],
		   [ 5,  $px, 1.375-1.8, 1.1, 1.0, "", "paste", 0,  ],
		   [ 6, -0.5*$px,   $y2,   $sx, $y3, "", "paste", 0,  ],
		   [ 6, -1.5*$px,   $y2,   $sx, $y3, "", "paste", 0,  ],
		   [ 6, -$px, 1.375, 1.1, 1.0, "", "paste", 0,  ],
		   [ 6, -$px, 1.375-1.8, 1.1, 1.0, "", "paste", 0,  ],
	       ];
    push @arr, [ @tmp ];

    $px = 0.75/2; $py = 0.9/2; $wx = 0.35;  $wy = 0.4;
    $D  = 1.1;    $E  = 1.0;   $sx = 0.25;  $sy = 0.3;
    $x2 = 0.4; $x3 = 0.3;
    push @arr, [   [ "SOT1215", "DFN1010D-3" ],
		   [   [ "lr", 0.18,  $D/2,-$E/2,   -$D,0,  0,$E,  $D,0,  0,-$E, ],
		       [ "lr", 0.12,  $px-$wx/2,-$E/2,  $wx/2,0.2,  $wx/2,-0.2, ],
		   ],
		   [   [ 1,   $px,  -$py,  $wx, $wy, "", "", 0, 0.05 ],
		       [ 2,  -$px,  -$py,  $wx, $wy, "", "", 0, 0.05 ],
		       [ 3,     0,   $py,  $x2, $wy, "", "", 0, 0.05 ],
		   ],
		   [   [ 1,   $px,  -$py,  $sx, $sy, "", "paste", 0, 0.05 ],
		       [ 2,  -$px,  -$py,  $sx, $sy, "", "paste", 0, 0.05 ],
		       [ 3,     0,   $py,  $x3, $sy, "", "paste", 0, 0.05 ],
		   ],
	       ];

    $px = 0.35; $py = (0.5+0.35)/2; $wx = 0.20;  $wy = 0.35;
    $D  = 1.1;  $E  = 1.0;          $sx = 0.20;  $sy = 0.25;
    push @arr, [   [ "SOT1216", "DFN1010B-6" ],
		   [   [ "lr", 0.18,  -$D/2,$E/2,   $D,0,  0,-$E,  -$D,0,  0,$E, ],
		       [ "lr", 0.12,  -$px-$wx/2,$E/2,  $wx/2,-0.2,  $wx/2,0.2, ],
		   ],
		   # solder mask 0.05 x-wise, but same height as pad
		   [   [ 1,  -$px,   $py,  $wx, $wy, "", "", 0, 0.05  ],
		       [ 2,     0,   $py,  $wx, $wy, "", "", 0, 0.05  ],
		       [ 3,   $px,   $py,  $wx, $wy, "", "", 0, 0.05  ],
		       [ 4,   $px,  -$py,  $wx, $wy, "", "", 0, 0.05  ],
		       [ 5,     0,  -$py,  $wx, $wy, "", "", 0, 0.05  ],
		       [ 6,  -$px,  -$py,  $wx, $wy, "", "", 0, 0.05  ],
		   ],
		   [   [ 1,  -$px,   $py,  $sx, $sy, "", "paste", 0, 0.05  ],
		       [ 2,     0,   $py,  $sx, $sy, "", "paste", 0, 0.05  ],
		       [ 3,   $px,   $py,  $sx, $sy, "", "paste", 0, 0.05  ],
		       [ 4,   $px,  -$py,  $sx, $sy, "", "paste", 0, 0.05  ],
		       [ 5,     0,  -$py,  $sx, $sy, "", "paste", 0, 0.05  ],
		       [ 6,  -$px,  -$py,  $sx, $sy, "", "paste", 0, 0.05  ],
		   ],
	       ];

    $py = 0.66;
    $px = 0.935;
    push @arr, [   [ "SOT1220", "DFN2020MD-6" ],
		   [   [ "lr", 0.18,  -1, 1,  2.0, 0,  0, -2,  -2.0, 0,  0, 2 ],
		       [ "lr", 0.10,  -1, -0.5,  0.5, -0.5 ],
		   ],
		   [   [ 1,  -$px,  -$py,  0.43, 0.35, "", "", 0, 0.05 ],
		       [ 2,  -$px,     0,  0.43, 0.35, "", "", 0, 0.05 ],
		       [ 3,  -$px,   $py,  0.43, 0.35, "", "", 0, 0.05 ],
		       [ 4,   $px,   $py,  0.43, 0.35, "", "", 0, 0.05 ],
		       [ 5,   $px,     0,  0.43, 0.35, "", "", 0, 0.05 ],
		       [ 6,   $px,  -$py,  0.43, 0.35, "", "", 0, 0.05 ],
		       # thoose two doesn't have a number in the pdf
		       [ 7,     0, -0.28,  1.10, 1.25, "", "", 0, 0.05 ],
		       [ 8,     0, 0.775,  0.66, 0.35, "", "", 0, 0.05 ],
		   ],
		   [   [ 1,  -$px,  -$py,  0.33, 0.25, "", "paste", 0, 0.05 ],
		       [ 2,  -$px,     0,  0.33, 0.25, "", "paste", 0, 0.05 ],
		       [ 3,  -$px,   $py,  0.33, 0.25, "", "paste", 0, 0.05 ],
		       [ 4,   $px,   $py,  0.33, 0.25, "", "paste", 0, 0.05 ],
		       [ 5,   $px,     0,  0.33, 0.25, "", "paste", 0, 0.05 ],
		       [ 6,   $px,  -$py,  0.33, 0.25, "", "paste", 0, 0.05 ],

		       [ 7,     0, -0.28,  0.90, 1.05, "", "paste", 0, 0.05 ],
		       [ 8,     0, 0.775,  0.56, 0.25, "", "paste", 0, 0.05 ],
		   ],
	       ];


    if ($test) {
	pad_gen($prefix, $doc_prefix, $test, $paste_as_outline);
	return;
    } else {
	for (my $ix = 0; $ix < @arr; $ix++) {
	    my $r = $arr[$ix];
	    pad_gen($prefix, $doc_prefix, $r, $paste_as_outline);
	}
    }
}
#gen_nexperia_smd(0);

sub gen_on_dual_cool_88() {
    my $file = "on_fairchild_dual_cool_88.fp";
    my $doc = "# https://www.onsemi.com/pub/Collateral/FDMT80060DC-D.pdf\n";
    # the package has pinname and pinnumbers: G 1, S 2-4, D 5-8

    element_start($file, $doc);
    my $w = 1.1;
    my $h = 1.13;
    my $p = 2;
    my $y = (9 - $h)/2;
    my @name = qw/ G S S S D D D D /;
    #silk_width(0.25);
    for (my $ix = 0; $ix < 4; $ix++) {
	pad($ix * $p - 3, $y, $w, $h, $name[$ix], 0, 0, $ix+1);
    }
    for (my $ix = 0; $ix < 4; $ix++) {
	pad(3 - $ix * $p, -$y, $w, $h, $name[$ix+4], 0, 0, $ix+5);
    }
    pad(1, 9/2 - $h + 0.48/2, 5.10, 0.48, "S", 0, 0, 2);
    pad(0, -(5.23/2 - 1.83), 6.9, 5.23, "D", 0, 0, 5);

    pr("# body\n");
    silk_crect([0,0], [8, 8]);

    element_stop();
}
#gen_on_dual_cool_88();

sub gen_yuden_power_inductor() {
    my $prefix = "taiyo_yuden";
    my $doc = "# yuden.co.jp: power_inductor_all_e.pdf\n";
    my $doc1 = "# page 2 (52) - 22 (61...): SMD POWER INDUCTORS(NR SERIES/NR SERIES H TYPE/S TYPE/V TYPE)\n\n";

    # page 2, part number tbl 2
    my $dim_tbl = # the "x" isn't ascii
"2010 2.0×2.0×1.0
2012 2.0×2.0×1.2
2410 2.4×2.4×1.0
2412 2.4×2.4×1.2
3010 3.0×3.0×1.0
3012 3.0×3.0×1.2
3015 3.0×3.0×1.5
4010 4.0×4.0×1.0
4012 4.0×4.0×1.2
4018 4.0×4.0×1.8
5010 4.9×4.9×1.0
5012 4.9×4.9×1.2
5014 4.9×4.9×1.4
5020 4.9×4.9×2.0
5024 4.9×4.9×2.4
5030 4.9×4.9×3.0
5040 4.9×4.9×4.0
6010 6.0×6.0×1.0
6012 6.0×6.0×1.2
6014 6.0×6.0×1.4
6020 6.0×6.0×2.0
6028 6.0×6.0×2.8
6045 6.0×6.0×4.5
8030 8.0×8.0×3.0
8040 8.0×8.0×4.0";
    my %dim;
    for (split(/\n/, $dim_tbl)) {
	# theese are all square with different height
	if (m/^(\d\d)\d\d (\d\.\d).*$/) {
	    my $k = $1;
	    my $v = $2;
	    if (!$dim{$k}) { $dim{$k} = [ $v ]; }
	}
    }
    #for my $k (sort keys %dim) { my $v = $dim{$k}; my $x = $$v[0]; print "$k: $x\n"; }

    # page 2, std ext. dim / rec. land patterns
    # all NRx's on same line has same first two digits
    my $pad_tbl =
"NRV2010
                          0.65 1.35    2.0
NRS2012, NRV2012
NRH2410
                          0.7  1.45    2.0
NRH2412
NR 3010, NRH3010
NR 3012, NRH3012, NRV3012 0.8  2.2     2.7
NR 3015, NRS3015
NR 4010, NRS4010
NR 4012, NRS4012          1.2  2.8     3.7
NR 4018, NRS4018
NRS8030
                          1.8  5.6     7.5
NR 8040, NRS8040
" . # plus page 3, rec. land patterns
"NRS5010
NRS5012
NRS5014
NRS5020          1.5 3.6 4.0
NRS5024
NRS5030
NR 5040, NRS5040
NRS6010
NR 6012, NRS6012
NRS6014
                 1.6 4.7 5.7
NR 6020, NRS6020
NR 6028, NRS6028
NR 6045, NRS6045
";
    #print $pad_tbl;
    my $lst = 0;
    for (split(/\n/, $pad_tbl)) {
	s/NR./NRx/g;
	tr/,\t\r\n / /s;
	if (m/( ?NRx(\d\d)\d\d)*(( \d+\.\d+)+)?/) {
	    my $p = "";
	    if ($1) {
		$p = $2;
		$lst = $p;
	    }
	    my $d = "";
	    if ($3) {
		$d = $3;
		$d =~ s/^ //;
		# A: width (x), B: center-center (x), C: height (y)
		my ($A, $B, $C) = split(/ /, $d);
		push @{$dim{$lst}}, ($A, $B, $C);
	    }
	    #print "<$p> <$d>\n";
	}
    }
    for my $k (sort keys %dim) {
	my $v = $dim{$k};
	my ($sz, $A, $B, $C) = @$v;
	my $file = $prefix . "_NRx" . $k . "xx.fp";

	print "$file: $sz $A $B $C\n";
	element_start($file, $doc . $doc1);
	pad(-$B/2, 0, $A, $C, "", "square", 0);
	pad( $B/2, 0, $A, $C, "", "square", 0);
	silk_sq($sz);
	element_stop();
    }

    {
	$doc1 = "# page 23 (62) - 32 (62...): SMD POWER INDUCTORS(NR SERIES/NR SERIES H TYPE/S TYPE/V TYPE)\n";
	my $k = "100";
	my ($sz, $A, $B, $C) = (10.0, 2.6, 5.4+2.6, 4.5) ;
	my $file = $prefix . "_NRx" . $k . "xx.fp";

	print "$file: $sz $A $B $C\n";
	element_start($file, $doc . $doc1);
	pad(-$B/2, 0, $A, $C, "", "square", 0);
	pad( $B/2, 0, $A, $C, "", "square", 0);
	silk_sq($sz);
	element_stop();
    }
}

#gen_yuden_power_inductor();

sub gen_fastron_smd() {
    my $name = "fastron";
    my $doc_common =
"# http://www.fastrongroup.com/part!show?categoryId=15
# Chip Inductors for Power Applications (shielded)\n";

    # a: oversized pads for easier handsoldering, b: less so, c: reflow soldered
    my @xsize = ( [ "a", 1.5, 1.0 ], [ "b", 1.0, 0.5 ], [ "c", 0,0 ] );

    for my $r (@xsize) {
	my $model = "1616fps";
	my $szsuff = $$r[0];
	my $szX  = $$r[1];
	my $szY  = $$r[2];
	my @pad = (1.4, 3.8, 1.4);

	my $file = sprintf("%s_%s_%s.fp", $name, $model, $szsuff);
	my $doc = $doc_common . "# $model\n";
	element_start($file, $doc);
	my $pw = $pad[0] + $$r[1];
	my $ph = $pad[1] + $$r[2];
	my $x = $pw/2 + $pad[2]/2;
	pad(-$x, 0, $pw, $ph, "", "", 0);
	pad( $x, 0, $pw, $ph, "", "", 0);
	silk_width(0.12);
	silk_crect([0,0], [3.6,4.2], -0.6);
	silk_width();
	silk_sq(4.2);
	element_stop();
    }
}
#gen_fastron_smd();

sub gen_eth_trafo() {
    my $name;
    my $doc;
    my @name;

    # 100BaseT
    $name = "bourns_PT61018AAPEL"; # same fp for  SM13072APEL, PT61018AAPEL-S
    $doc  = "# http://www.farnell.com/datasheets/2169309.pdf\n"
	.   "# http://www.farnell.com/datasheets/2169310.pdf\n"
	.   "# http://www.farnell.com/datasheets/2240885.pdf\n";
    @name = qw/ TD+ CT_TD TD- N.C. N.C. RD+ CT_RD RD- RX- CT_RX RX+ N.C. N.C. TX- CT_TX TX+ /;

    pkg_smdpins($name, $doc, [16/2,0], [1.27, 0.76, (10.5-7.10)/2, 0],
		[ 12.8, 6.9, 0.3, -1 ], [0, (10.5+7.1)/4], undef, undef, \@name);

    # 1000BaseT

    $name = "abracon_ALANS10001";
    $doc  = "# http/www.farnell.com/datasheets/2828019.pdf\n";
    @name = qw/TCT1 TD1+ TD1- TCT2 TD2+ TD2- TCT3 TD3+ TD3- TCT4 TD4+ TD4-
		  MX4- MX4+ MCT4 MX3- MX3+ MCT3 MX2- MX2+ MCT2 MX1- MX1+ MCT1 /;

    pkg_smdpins("${name}_3", $doc, [24/2,0], [1.27, 0.76, (16.51-12.7)/2, 0],
		[18.38, 12.44, 0.3, -1], [0, (16.51+12.7)/4], undef, undef, \@name);

    pkg_smdpins("${name}_4", $doc, [24/2,0], [0.99, 0.64, (19.56-15.49)/2, 0],
		[13.95, 15.49, 0.3, -1], [0, (19.56+15.49)/4], undef, undef, \@name);

    $name = "bourns_PT61020L";
    $doc  = "# http://www.farnell.com/datasheets/1900896.pdf\n";

    pkg_smdpins($name, $doc, [24/2,0], [1.27, 0.76, 1.91, 0],
		[17.62, 12.20, 0.3, -1], [0, (16.51-1.91)/2], undef, undef, \@name);

    $name = "bourns_SM51589PEL";
    $doc  = "# http://www.farnell.com/datasheets/2907615.pdf\n";
    @name = reverse(@name);

    pkg_smdpins($name, $doc, [24/2,0], [1.27, 0.64, (16.5-12.7)/2, 0],
		[17.55, 12.2, 0.3, -1], [0, (16.5+12.7)/4], undef, undef, \@name);

}
#gen_eth_trafo();

sub gen_ixys_sop() {
    my $name = "ixys_sop";
    my $doc  = "# https://docs-emea.rs-online.com/webdocs/1471/0900766b81471bc1.pdf p6/6\n";
    my @name = qw/ Control+ Control- Load Load /;

    my  (   $b,    $D,    $E,   $E1,   $e,  $h,    $L, $N ) =
	(0.381, 4.089, 6.096, 3.810, 2.54, 0.4, 0.432,  4 );

    pkg_smdpinsR($name, $doc, [$N/2, 0], [$e, $b, $L], [$D, $E1, 0, $h], [$D,$E], undef, undef, \@name);
}
#gen_ixys_sop();

sub gen_omron_a6s_h() {
    my $doc  = "# http://www.farnell.com/datasheets/2340746.pdf\n";

    my (  $b,  $E, $E1,   $e,   $h,  $L) =
	(0.5, 9.8, 6.2, 2.54, -1.0, 0.7);

    for (my $ix = 0; $ix < 10; $ix++) {
	my $N = 2*($ix + 1);
	my $A = 3.48 + $e * $ix;
	my $var = sprintf "omron_a6s-%01d10x-H", ($ix+1)%10;
	pkg_smdpinsR($var, $doc, [$N/2, 0], [$e, $b, $L], [$A, $E1, 0, $h], [$A,$E]);
    }
}
#gen_omron_a6s_h();

sub gen_murata_ntv() {
    my $name = "murata_ntv";
    my $doc  = "# http://www.farnell.com/datasheets/1965134.pdf\n";

    my  (  $b,    $D,   $E, $E1,   $e,    $h,  $L,  $N ) =
	( 0.6, 15.24, 10.8, 7.7, 1.27, undef, 1.35, 22 );

    my @name = (
	"-Vin", undef, "+Vin", undef, "NA", undef, undef, undef, "0V", undef, "-Vout",
	"NA", undef, "+Vout", undef, undef, undef, "NA", undef, "NA", undef, "NA",
    );
    my @num = (
	01, undef,  3, undef,     5, undef, undef, undef,  9, undef, 11,
	12, undef, 14, undef, undef, undef,    18, undef, 20, undef, 22,
    );
    pkg_smdpinsR($name, $doc, [$N/2, 0], [$e, $b, $L], [$D, $E1, 0, $h], [$D,$E], undef, \@num, \@name);
}
#gen_murata_ntv();

sub gen_FOD817() {
    my $name = "fod817";
    my $doc  = "# http://www.farnell.com/datasheets/2303998.pdf\n";

    my  (   $b,  $D,   $E, $E1,   $e,    $h,  $L, $N ) =
	( 1.25, 4.6, 10.1, 6.5, 2.54, undef, 1.0,  4 );

    my @name = qw/ Anode Cathode Emitter Collector /;
    pkg_smdpinsR($name, $doc, [$N/2, 0], [$e, $b, $L], [$D, $E1, 0, $h], [$D,$E], undef, undef, \@name);
}
#gen_FOD817();

sub get_microchip_RN2483() {
    my $file = "rn2483.fp";
    my $doc  =
"# http://ww1.microchip.com/downloads/en/DeviceDoc/RN2483-Low-Power-Long-Range-LoRa-Technology-Transceiver-Module-Data-Sheet-DS50002346D.pdf
# http://ww1.microchip.com/downloads/en/DeviceDoc/RN2483-LoRa-Technology-Module-Command-Reference-User-Guide-DS40001784G.pdf
";
    my @name = qw/
GND
UART_RTS
UART_CTS
RESERVED
RESERVED
UART_TX
UART_RX
GND
GPIO13
GPIO12
GND
VDD
GPIO11
GPIO10
NC
NC
NC
NC
NC
GND
GND
GND
RFH
GND
RFL
GND
GND
GND
NC
PGC_INT
PGD_INT
\_RESET\_
GND
VDD
GPIO0
GPIO1
GPIO2
GPIO3
GPIO4
GPIO5
GND
NC
GPIO6
GPIO7
GPIO8
GPIO9
GND
/;

    element_start($file,$doc);
    my $mx = 26.67;
    my $ex = $mx / 2;
    my $my = 17.78;
    my $ey = $my / 2;
    my $px = 1.016;
    my $py = 1.524;
    my $sm = 0.1;
    my $p  = 1.27;
    my $rr = ipc_corner($px);
    $mask_gap  = $sm;

    my $ix;
    for ($ix = 0; $ix < 20; $ix++) {
	my $name = shift @name;
	pad($ex - $p - $ix*$p, -$my/2, $px, $py, $name, "", $rr);
    }
    for ($ix = 0; $ix < 7; $ix++) {
	my $name = shift @name;
	pad(-$ex, -$p*3 + $p*$ix, $py, $px, $name, "", $rr);
    }
    for ($ix = 0; $ix < 20; $ix++) {
	my $name = shift @name;
	pad(-$ex+$p + $ix*$p, $ey, $px, $py, $name, "", $rr);
    }
    my $xsta = $ex - $p + $px/2 + $sm + $silk_default/2;
    my $ysta = $p*3 + $px/2 + $sm + $silk_default/2;
    silk_start($xsta, -$ey);
    silk_line( $ex, -$ey);
    silk_line( $ex, $ey);
    silk_line($xsta, $ey);

    silk_start(-$xsta, -$ey);
    silk_line(-$ex, -$ey);
    silk_line(-$ex, -$ysta);

    silk_start(-$xsta, $ey);
    silk_line(-$ex, $ey);
    silk_line(-$ex, $ysta);

    element_stop();
    $mask_gap  = $mask_gap_default;
}
#get_microchip_RN2483();

########################################
## mixed footprints ####################
########################################

sub gen_telit_gm862() {
  my $ix;
  my $x = -6;
  element_start("telit_gm862.fp", "# telit gsm/gps module GM862
# http://www.telit.com/module/infopool/download.php?id=537

# it contains a:
# molex smt board to board connector plug, 50 ways
# http://www.molex.com/pdm_docs/sd/537480504_sd.pdf

# for some reason, pin number 1 is not the one with a notch in telit doc., its pin number 2
# here we follow telits numbering

# origo is connector center
");

  for ($ix = 0; $ix < 25; $ix++) {
    pad( $x,  1.7, 0.25, 1.2);
    pad( $x, -1.7, 0.25, 1.2);
    $x += 0.5;
  }

  pr();
  pr("ElementLine[  -7.65mm -2.15mm    8.15mm -2.15mm  0.25mm ]\n");
  pr("ElementLine[   8.15mm -2.15mm    8.15mm  2.15mm  0.25mm ]\n");
  pr("ElementLine[   8.15mm  2.15mm   -8.15mm  2.15mm  0.25mm ]\n");
  pr("ElementLine[  -8.15mm  2.15mm   -8.15mm -1.65mm  0.25mm ]\n");
  pr("ElementLine[  -8.15mm -1.65mm   -7.65mm -2.15mm  0.25mm ]\n");

  my $x1 = -(43.1/2 + 9.75);
  my $x2 =  (43.1/2 - 9.75);
  my $y1 = -(43.1/2 - 14.6);
  my $y2 =  (43.1/2 + 14.6);

  pr("# left side pins\n");
  pin($x1, 14.6, 1.1, 2.4);
  pin($x1,  4.6, 1.1, 2.4);
  pin($x1, 24.6, 1.1, 2.4);

  pr("# right side pins\n");
  pin($x2, 14.6, 1.1, 2.4);
  pin($x2,  4.6, 1.1, 2.4);
  pin($x2, 24.6, 1.1, 2.4);

  pr("# top side pins\n");
  pin(-9.75, $y1, 1.1, 2.4);

  pr("# bottom side pins\n");
  pin(-9.75, $y2, 1.1, 2.4);

  $bbx1 = -(43.9/2 + 9.75);
  $bbx2 =  (43.9/2 - 9.75);
  $bby1 = -(43.9/2 - 14.6);
  $bby2 =  (43.9/2 + 14.6);
  silk_bb(0.32);
  element_stop();
}
#gen_telit_gm862();

sub gen_camden_cnmb_all() { # TODO
    my $doc = "
# Camdenboss Din rail boxes, model CNMB in sizes 1-12
# catalogue pages http://camdenboss.com/media/category/files/04_din_rail_boxes_8.pdf
# theese boxes has each five possible pcb board positions/sizes named A .. E
";
    my @size = ( 1, 2, 3, 4, 5, 6, 9, 12 );
    # article name is "CNMB/$size"
    my @doc = ( # [size]
	# drawings
	"# http://camdenboss.com/fileuploader/download/download/?d=0&file=custom%2Fupload%2FCNMB%3D1%3D2.pdf", # 1
	"# http://camdenboss.com/fileuploader/download/download/?d=0&file=custom%2Fupload%2FCNMB%3D2%3D2.pdf", # 2
	"# http://camdenboss.com/fileuploader/download/download/?d=0&file=custom%2Fupload%2FCNMB%3D3%3D2.pdf", # 3
	"# http://camdenboss.com/fileuploader/download/download/?d=0&file=custom%2Fupload%2FCNMB%3D4%3D2.pdf", # 4
	"# http://camdenboss.com/fileuploader/download/download/?d=0&file=custom%2Fupload%2FCNMB%3D5%3D2.pdf", # 5
	"# http://camdenboss.com/fileuploader/download/download/?d=0&file=custom%2Fupload%2FCNMB%3D6%3D2.pdf", # 6
	"# http://camdenboss.com/fileuploader/download/download/?d=0&file=custom%2Fupload%2FCNMB%3D9%3D2.pdf", # 9
	"# http://camdenboss.com/fileuploader/download/download/?d=0&file=custom%2Fupload%2FFile-1392199389.pdf", # 12
    );

    # general dimensions, X = horizontal width, Y is vertical width, Z is height
    my $genY_board_E_separation = 20.4;
    my $gen_cover_thickness = 1.5; # thinkness of outer frame
    my $genY_top_ext = 45;
    #my $genY_top_int = 42; # pcb size pos C
    my $genY_mid_ext = 62;
    #my $genY_mid_int = 57; # pcb size pos B
    my $genY_bot_ext = 90;
    #my $genY_bot_int = 86.5; # pcb size pos A
    my $genY_clip_hole_cc = 99.5; # 11 + 8 + 90
    my $gen_clip_hole_dia =  4.1;
    my $gen_clip_Ytop = 10.5; # frame to clip end, top
    my $gen_clip_Ybot = 7.8; # frame to clip end, bot
    my $gen_clip_Yxtra = 4.4; # clip end to hole center
    my $gen_clip_wtop = 11.5;
    my $gen_clip_wbot = 10;
    my $gen_clip_Wtop = 15; # width of clip holder in base
    my $gen_clip_Wbot = 13; # width of clip holder in base

    my $gen_base_thickness = 2; # thinkness of bottom plate
    my $genY_base_bump = 41;

    # size                1      2     3     4     5      6      9     12
    my @gen_clip_botX = (  0  ,  0  ,  0  ,  0  , 42.6,  60.6, 113.8, 166.8 );
    my @genX_overall  = ( 17.5, 36  , 53  , 71.2, 88  , 106.2, 159.2, 212.1 ); # 0 = TODO
    # mounting holes for pcb flat on base; mostly useless I guess # TODO
    my @genX_mholes   = (  0  , 21  , 32.4, 50.2, 67  ,  85  , 138  , 191   );
    my @genX_B_sep    = (  3.7, 22.2, 39.2, 57  , 73.8,  92  , 145  , 197.9 );

    my $base_snap_x = 6;
    my $base_snap_y = 1.8;
    my @base_snap_pos = ( # TODO
	[ ], # 1
	[ ], # 2
	[ ], # 3
	[ ], # 4
	[ ], # 5
	[ ], # 6
	[ ], # 9
	[ ], # 12
    );

    # board A is bottom, B mid height, C top pcb; D = standing vertical pcb, E is standing horizontal pcb
    my @pcb_board = ( "A", "B", "C", "D", "E" ); # names of board posistions
    my @pcbY     = ( 86.5, 57,  42,  34,  40 ); #except for CNMB/1, where C = 41.8
    my $pcbY_C_1 = 41.8;

    my @pcbX = ( # [size][board position]
	#  A    B    C    D     E
	[  14,  14,  14, 59.6,  14.8 ], # 1
	[  33,  32,  32, 59.6,  33   ], # 2
	[  50,  49,  49, 59.6,  50   ], # 3
	[  68,  67,  67, 59.6,  68   ], # 4
	[  84,  83,  83, 59.6,  84   ], # 5
	[ 103, 102, 102, 59.6, 103   ], # 6
	[ 155, 154, 154, 59.6, 155   ], # 9
	[ 208, 207, 207, 59.6, 208   ], # 12
    );

    for (my $six = 0; $six < @size; $six++) {
	my $size = $size[$six];
	my $file_stem = "cnmb$size";
	my $ddoc = "# http://camdenboss.com/media/category/files/04_din_rail_boxes_8.pdf\n" . $doc[$six] . "\n";

	# make pcb board pos. A
	my $bix = 0; # board A
	element_start($file_stem . '_a.fp', $ddoc);
	silk_width(0.12);
	silk_crect([0,0], [$genX_overall[$six], $genY_bot_ext], 0);
	silk_crect([0,0], [$genX_overall[$six] - $gen_cover_thickness, $genY_bot_ext - $gen_cover_thickness], 0);
	# top clip
	silk_start( -$gen_clip_wtop/2, -$genY_bot_ext/2);
	silk_rline( 0, -$gen_clip_Ytop);
	silk_rline( $gen_clip_wtop, 0);
	silk_rline( 0,  $gen_clip_Ytop);
	silk_circle([0, - $genY_bot_ext/2 - $gen_clip_Ytop + $gen_clip_Yxtra], $gen_clip_hole_dia/2);
	# bottom clips
	my $dist = $gen_clip_botX[$six]/2;
	my @dist = (-$dist);
	if ($dist) { push @dist, $dist; }
	for my $d (@dist) {
	    silk_start( -$gen_clip_wbot/2 + $d, $genY_bot_ext/2);
	    silk_rline( 0,  $gen_clip_Ybot);
	    silk_rline( $gen_clip_wbot, 0);
	    silk_rline( 0, -$gen_clip_Ybot);
	    silk_circle([$d, $genY_bot_ext/2 + $gen_clip_Ybot - $gen_clip_Yxtra], $gen_clip_hole_dia/2);
	}
	# base plate
	silk_width();
	silk_crect([0,0], [$pcbX[$six][$bix], $pcbY[$bix]], 0);
	silk_width(0.12);
	silk_crect([0,0], [$pcbX[$six][$bix] - 2*$gen_base_thickness, $pcbY[$bix] - 2*$gen_base_thickness], 0);

	#silk_crect([-($pcbX[$six][$bix] - 2*$gen_base_thickness)/2, $$genY_base_bump/2], );
	#silk_crect([0,0], [$pcbX[$six][$bix] - 2*$gen_base_thickness, $pcbY[$bix] - 2*$gen_base_thickness], 0);

	element_stop();

	#for (my $bix = 0; $bix < @pcb_board; $bix++) {
	#}
    }

}
#gen_camden_cnmb_all();

########################################
# some special things

sub led_spot_holder_a() {
    my $file = "led_spot_holder_a.fp";
    my $doc  = "# as measured\n";
    my $desc = "";
    my $refdes = "M?";
    my $value = "";
    element_start($file, $doc, $desc, $refdes, $value);
    pin(-7.5, 0, 4.5, 5.5, "m", "", "1");
    pin(7.5, 0, 4.5, 5.5, "m", "", "1");
    pin(0, -8.5, 3.5, 5.5, "m", "", "1");
    pin(0, 8.5, 3.5, 5.5, "m", "", "1");
    silk_circle($origin, 22.5);
    element_stop();
}
#led_spot_holder_a();

sub line_arc() {
    my @first = ( 70, 40 ); # pos of first via
    my @step  = (  1,  0.5 ); # distance between vias
    my $pol   = vec_polar(\@step);
    my $flg   = '"clearline"';

    my $th = mk_mm(0.15);
    my $cl = mk_mm(0.15);


    my $start_angle = -rad_deg( $$pol[1] );
    my $sweep = 2*$start_angle;

    my $mrad = mk_mm($$pol[0]/2);
    my $ang = 180 + $start_angle;
    my $astr = "";
    my ($x1, $y1, $x2, $y2);

    $x1 = mk_mm($first[0]);
    $y1 = mk_mm($first[1]);
    $x2 = mk_mm($first[0] + $step[0]);
    $y2 = mk_mm($first[1] + $step[1]);
    $astr .= "\tArc  [ $x1 $y1 $mrad $mrad $th $cl  $ang  -$sweep $flg ]\n";
    $astr .= "\tArc  [ $x2 $y2 $mrad $mrad $th $cl  -$start_angle  $sweep $flg ]\n";

    $x1 = mk_mm($first[0] + 2);
    $y1 = mk_mm($first[1]);
    $x2 = mk_mm($first[0] + 2 - $step[0]);
    $y2 = mk_mm($first[1] + $step[1]);
    $astr .= "\tArc  [ $x1 $y1 $mrad $mrad $th $cl  -$start_angle  $sweep $flg ]\n";
    $astr .= "\tArc  [ $x2 $y2 $mrad $mrad $th $cl  $ang  -$sweep $flg ]\n";

    my $dy = - $$pol[0] * sin($$pol[1]) / 2;

    $x1 = mk_mm($first[0] + $step[0]/2);
    $y1 = mk_mm($first[1] - 2);
    $y2 = mk_mm($first[1] - $dy );
    my $lstr = "";
    $lstr .= "\tLine [ $x1 $y1 $x1 $y2 $th $cl $flg ]\n";
    $y1 = mk_mm($first[1] + $step[1] + $dy );
    $y2 = mk_mm($first[1] + $step[1] + 2);
    $lstr .= "\tLine [ $x1 $y1 $x1 $y2 $th $cl $flg ]\n";

    $x1 = mk_mm($first[0]+1 + $step[0]/2);
    $y1 = mk_mm($first[1] - 2);
    $y2 = mk_mm($first[1] - $dy );
    $lstr  .= "\tLine [ $x1 $y1 $x1 $y2 $th $cl $flg ]\n";
    $y1 = mk_mm($first[1] + $step[1] + $dy );
    $y2 = mk_mm($first[1] + $step[1] + 2);
    $lstr .= "\tLine [ $x1 $y1 $x1 $y2 $th $cl $flg ]\n";

    print $lstr, $astr;
}
#line_arc();

sub gen_cust_001() {
    element_start("cust_001.fp", "# special controller panel\n");
    my $dx = 142/2;
    my $dy =  72/2;
    my $x;
    my $y;
    silk_width(0.25);
    pr("# M3 mounting pins\n");
    pin(  12.4-$dx, 12.5-$dy,  3.38, 8.0, "GND", "");
    pin(  13.3-$dx, 60.0-$dy,  3.38, 8.0, "GND", "");
    pin(  72.5-$dx, 33.0-$dy,  3.38, 8.0, "GND", "");
    pin(  80.5-$dx, 60.0-$dy,  3.38, 8.0, "GND", "");
    pin( 129.5-$dx, 30.8-$dy,  3.38, 8.0, "GND", "");
    pr("\n");
    pr("# 5.1 mm holes for led\n");
    $y = mk_mm(15-$dy);
    for ((28, 53, 78, 103, 128)) {
	$x = mk_mm($_-$dx);
	pr("ElementArc [ $x $y  2.5mm 2.5mm 0 360 0.25mm ]\n");
	silk_cross( $_-$dx, 15-$dy, 2, 0.18);
    }
    $x = mk_mm(78-$dx);
    $y = mk_mm(43-$dy);
    pr("ElementArc [ $x $y  2.5mm 2.5mm 0 360 0.25mm ]\n");
    silk_cross( 78-$dx, 43-$dy, 2, 0.18);
    pr("\n");
    pr("# dia 17mm holes for push buttons\n");
    $y = mk_mm(50-$dy);
    for ((21, 46, 71, 121)) {
	my $x = mk_mm($_-$dx);
	pr("ElementArc [ $x $y  8.5mm 8.5mm 0 360 0.25mm ]\n");
	silk_cross( $_-$dx, 50-$dy, 4, 0.18);
    }
    pr("\n");
    pr("# hour counter square hole\n");
    silk_crect([ 96-$dx, 50-$dy ], [ 25, 25 ], 0);
    silk_cross( 96-$dx, 50-$dy, 4, 0.18);
    pr("\n");
    pr("# recommended outline of pcb\n");
    silk_width(0.32);
    silk_rect([8-$dx, 8-$dy], [ 142-8-$dx, 72-8-$dy], 0);

    element_stop();
}
#gen_cust_001();

sub gen_cust_002($) {
    my $full = shift;

    element_start("cust_002$full.fp", "  # special control panel\n");

    if ($full eq "a") {
	pr "# Panel outline\n";
	silk_width(0.32);
	silk_start( 0,  2 );
	silk_line(  0, 68 );

	silk_start(  2, 70 );
	silk_line( 103, 70 );

	silk_start(105, 68 );
	silk_line( 105,  2 );

	silk_start(103,  0 );
	silk_line(   2,  0 );

	silk_arc( [  2, 68], 2,   0, 90);
	silk_arc( [103, 68], 2,  90, 90);
	silk_arc( [103,  2], 2, 180, 90);
	silk_arc( [  2,  2], 2, 270, 90);
    }
    my @pos = (
	"M4 mounting pins",
	[   6.00,   5.90,  4.2 ],
	[   6.00,  64.10,  4.2 ],
	[  99.10,  64.10,  4.2 ],
	[  99.10,   5.90,  4.2 ],
	"Pushbutton",
	[  24.90,  14.50, 12.0 ],
	"Potensiometer",
	[  45.25,  22.60,  6.3 ],
	"Summer",
	[  63.00,  15.50,  6.0 ],
	[  72.95,  15.50,  6.0 ],
	"M3 mounting pins",
	[  41.90,  12.50,  3.5 ],
	[  81.00,  12.50,  3.5 ],
	[  81.00,  59.10,  3.5 ],
	[  19.10,  59.10,  3.5 ],
	"Left leds",
	[  24.90,  29.00,  3.0 ],
	[  24.90,  34.10,  3.0 ],
	[  24.90,  39.20,  3.0 ],
	[  24.90,  44.30,  3.0 ],
	[  24.90,  49.40,  3.0 ],
	[  24.90,  54.50,  3.0 ],
	"Right leds",
	[  61.50,  29.00,  3.0 ],
	[  61.50,  34.10,  3.0 ],
	[  61.50,  39.20,  3.0 ],
	[  61.50,  44.30,  3.0 ],
	[  61.50,  49.40,  3.0 ],
	[  61.50,  54.50,  3.0 ],
    );

    #print "       x       y     dia\n";
    my $ix = 7;
    if ($full) {
	$ix = 0;
    }
    my $flg = 0;
    for (; $ix < @pos; $ix++) {
	my $pos = $pos[$ix];
	if (ref($pos) eq "ARRAY") {
	    $round_first_pin = 1;
	    my ($x, $y, $drill) = @$pos;
	    if ($flg) {
		pin( $x, 70-$y, $drill, 7, "mnt", "hole", 1);
	    } elsif ($full eq "a") {
		my @th = drill2thickness($drill);
		pin( $x, 70-$y, $drill, $th[1], "mnt", "", 1);
	    } elsif ($full eq "b" && 7 < $ix) {
		silk_cross( $x, 70-$y, $drill);
	    } else {
	    }
	    #printf "  [ %6.2f, %6.2f, %4.1f ],\n", $x, $y, $drill;
	} else {
	    if ($pos =~ m/^M3/) { $flg = 1; }
	    else { $flg = 0; }
	    pr "# $pos\n";
	    #print $pos, "\n";
	}
    }

    {
	my ($dx, $dy, $dia) = @{$pos[16]};
	#print join(", ", @pp), "\n";
	pr("# recommended outline of pcb\n");
	my $xmax = 70;
	my $ymax = 54.25;
	my $xcut = 23;
	my $ycut = 15;

	silk_width(0.32);
	silk_start( $dx-4, 70-$dy-4 );
	silk_rline( $xmax,     0);
	silk_rline(     0, $ymax);
	silk_rline( -$xmax + $xcut, 0);
	silk_rline( 0, - $ycut);
	silk_rline(  -$xcut, 0);
	silk_rline(  0, - $ymax + $ycut);
    }

    element_stop();
}
#gen_cust_002("a");
#gen_cust_002("b");
#gen_cust_002("c");

__END__



	silk_width(0.1);
	# right leds
	silk_start( $xtot - 23, -$ytot + 4);
	silk_line ( $xtot - 23,  $ycut - 4);
	silk_start( $xtot - 23-4, -$ytot + 9);
	silk_line ( $xtot - 23+4, -$ytot + 9);
	silk_start( $xtot - 23-4, -$ytot + 9+25);
	silk_line ( $xtot - 23+4, -$ytot + 9+25);
	# left leds
	silk_start(-$xtot + 10, -$ytot + 4);
	silk_line (-$xtot + 10,  $ycut - 4);
	silk_start(-$xtot + 10-4, -$ytot + 9);
	silk_line (-$xtot + 10+4, -$ytot + 9);
	silk_start(-$xtot + 10-4, -$ytot + 9+25);
	silk_line (-$xtot + 10+4, -$ytot + 9+25);

	# pot
	silk_start( $xtot - 40,  $ytot - 14-4);
	silk_line ( $xtot - 40,  $ytot - 14+4);
	silk_start( $xtot - 40-4,  $ytot - 14);
	silk_line ( $xtot - 40+4,  $ytot - 14);

	silk_width();






sub rangeTest() {
    my @range = ( [0,10], [50,220], [3,25], [2,34], [241,343], [3,23] );
    my @data = ( [20,54], [33,34], [1,3], [533,2421] );

    @range = rangeSort(@range);
    @range = rangeMerge(@range);

    print "sort: "; rangePrint(@range);
    print "merg: "; rangePrint(@range);
    @range = rangeAdd(@range, @data);
    print "add : "; rangePrint(@range);
    print "\n";

    @range   = ( [5,10], [15,20], [25,30], [35,40], [45,50] );
    my @excl = ( [1,2], [3,6], [12,21], [27,28], [29,31] );
    print "rang: "; rangePrint(@range);
    print "excl: "; rangePrint(@excl);
    @range = rangeExcl(@range, @excl);
    print "result: "; rangePrint(@range);
    exit(0);
}


sub line_intersect($$) { # find itersection point of two line segments
    # TODO or remove
    my $line_a = shift; # [ [x1,y1], [x2,y2] ], line from x1,y1 to x2,y2
    my $line_b = shift;

    my @ax = $$line_a[0][0] < $$line_a[1][0];
    my @ay;
    my @bx;
    my @by;

    my @aa = @{$$line_a[0]};
    my @ab = @{$$line_a[1]};
    my @ba = @{$$line_b[0]};
    my @bb = @{$$line_b[1]};

    if ($aa[0] < $ba[0] && $aa[0] < $bb[0]  && $ab[0] < $ba[0] && $ab[0] < $bb[0]) { # a to the left of b
	return undef;
    }

    if ($aa[0] > $ba[0] && $aa[0] > $bb[0]  && $ab[0] > $ba[0] && $ab[0] > $bb[0]) { # a to the right of b
	return undef;
    }

    if ($aa[1] < $ba[1] && $aa[1] < $bb[1]  && $ab[1] < $ba[1] && $ab[1] < $bb[1]) { # a above b
	return undef;
    }

    if ($aa[1] > $ba[1] && $aa[1] > $bb[1]  && $ab[1] > $ba[1] && $ab[1] > $bb[1]) { # a below b
	return undef;
    }

    if ($aa[0] == $ab[0]) {
	if ($ba[0] == $ba[1]) {
	    if ($aa[0] != $ba[0]) {
		return undef;
	    }
	    my $x = $aa[0];
	    my $amin = $aa[1];
	    if ($amin > $ab[1]) { $amin = $ab[1]; }
	    my $amax = $aa[1];
	    if ($amax < $ab[1]) { $amax = $ab[1]; }

	    my $bmin = $aa[1];
	    if ($bmin > $ab[1]) { $bmin = $ab[1]; }
	    my $bmax = $aa[1];
	    if ($bmax < $ab[1]) { $bmax = $ab[1]; }

	    my $ymin = $amin;
	    if ($ymin > $bmin) { $ymin = $bmin; }
	}
    }
}

sub bb_relative($$) {
    my $pos = shift;
    my $bb  = shift;

    my $x = $$pos[0];
    my $y = $$pos[1];

    my ($xmin, $xmax, $ymin, $ymax, $pin_no, $bbr) = @$bb;
    my ($Xmin, $Xmax, $Ymin, $Ymax) = ($xmin - $x, $xmax - $x, $ymin - $y, $ymax - $y);
    my @r;		      # distance from $pos bounding box corner
    $r[0] = triangle_r($Xmin,$Ymin);	 # top left
    $r[1] = triangle_r($Xmax,$Ymin);	 # top right
    $r[2] = triangle_r($Xmax,$Ymax);	 # bottom right
    $r[3] = triangle_r($Xmin,$Ymax);	 # bottom left

    my @a;	     # angle to corner point ( with pos at the center)
    $a[0] = PcbAngle($Xmin,$Ymin);     # top left
    $a[1] = PcbAngle($Xmax,$Ymin);     # top right
    $a[2] = PcbAngle($Xmax,$Ymax);     # bottom right
    $a[3] = PcbAngle($Xmin,$Ymax);     # bottom left

    ( \@r, \@a );
}
sub bb_relative_list($@) {
    my $pos = shift;
    my @bb = @_;

    my @arr;
    for my $bb (@bb) {
	push @arr, [ bb_relative($pos, $bb) ];
    }
    @arr;
}

sub testing() {
    my @bb;
    my $r;
    my $sweep;
    my $pos;
    my $sta;
    my $end;
    my @bbr = bb_relative($pos, @bb);
    my @arr;
    for my $bb (@bbr) {
	my @tt = @$bb;
	next if ($r < $tt[0] && $r < $tt[1] && $r < $tt[2] && $r < $tt[3]);
	next if ($r > $tt[0] && $r > $tt[1] && $r > $tt[2] && $r > $tt[3]);
	if ($sweep < 360) {
	    next if(
		!in_angle($sta, $end, $tt[4]) &&
		!in_angle($sta, $end, $tt[5]) &&
		!in_angle($sta, $end, $tt[6]) &&
		!in_angle($sta, $end, $tt[7])
	    );
	}
	push @arr, [ @tt ];
    }
}
