#! /usr/bin/perl

use strict;
use warnings;

if( @ARGV < 7 ) {
  print( STDERR "usage: $0 <pins X> <pins Y> <pin spacing (mm)> <pin width (mm)> <pin length (mm)> <side length X (mm)> <side length Y (mm)>\n" );
  exit( -1 );
}
my $pins_x = int( $ARGV[0] );
my $pins_y = int( $ARGV[1] );
my $pin_spacing = $ARGV[2];
my $pin_width = $ARGV[3];
my $pin_len = $ARGV[4];
my $side_x_len = $ARGV[5];
my $side_y_len = $ARGV[6];

my $pin_dist = $pin_spacing;
my $pin_begin = 0.5;

my $silk_dist = 0.3;

my $pcb_clearance = 3000;
my $pcb_solder_add = 400;

my $pcb_silk_width = 700;

sub mm2pcb
{
  my $mm = shift;
  my $pcb = $mm / 0.000254;
  my $pcb_i = $pcb < 0 ? int( $pcb - 0.5 ) : int( $pcb + 0.5 );
  return $pcb_i;
}

sub pad
{
  my ($x1, $y1, $x2, $y2, $no) = @_;
  my $dx = abs( $x2 - $x1 );
  my $dy = abs( $y2 - $y1 );
  my $width = $dx < $dy ? $dx : $dy;
  my $width2 = $width / 2;
  my $cx = ($x1 + $x2) / 2;
  my $cy = ($y1 + $y2) / 2;
  my $dx1 = $x1 - $cx;
  my $dx2 = $x2 - $cx;
  my $dy1 = $y1 - $cy;
  my $dy2 = $y2 - $cy;
  $x1 += $dx1 < 0 ? $width2 : -$width2;
  $x2 += $dx2 < 0 ? $width2 : -$width2;
  $y1 += $dy1 < 0 ? $width2 : -$width2;
  $y2 += $dy2 < 0 ? $width2 : -$width2;
  my $pcb_width = mm2pcb( $width );
  printf( "\tPad[%d %d %d %d %d %d %d \"%d\" \"%d\" \"square\"]\n", mm2pcb( $x1 ), mm2pcb( $y1 ), mm2pcb( $x2 ), mm2pcb( $y2 ), $pcb_width, $pcb_clearance, $pcb_width + $pcb_solder_add, $no, $no );
}

sub line
{
  my ($x1, $y1, $x2, $y2) = @_;
  printf( "\tElementLine[%d %d %d %d %d]\n", mm2pcb( $x1 ), mm2pcb( $y1 ), mm2pcb( $x2 ), mm2pcb( $y2 ), $pcb_silk_width );
}

my $d_side_x = $side_x_len / 2;
my $d_side_y = $side_y_len / 2;
my $d_pins_inner_x = $d_side_x + $pin_begin;
my $d_pins_inner_y = $d_side_y + $pin_begin;
my $d_pins_outer_x = $d_pins_inner_x + $pin_len;
my $d_pins_outer_y = $d_pins_inner_y + $pin_len;

my $d_corner_x = $d_side_x + $silk_dist;
my $d_corner_y = $d_side_y + $silk_dist;
my $d_corner_pins_x = $d_corner_x - $pin_dist;
my $d_corner_pins_y = $d_corner_y - $pin_dist;

my $d_outline_x = $d_pins_outer_x + $silk_dist;
my $d_outline_y = $d_pins_outer_y + $silk_dist;

my $name_pitch = sprintf( "%f", $pin_spacing );
$name_pitch =~ s/[^0-9]//g;
$name_pitch =~ s/0*$//g;
my $name = "QFP" . sprintf( "%d", ($pins_x + $pins_y) * 2 ) . "_R" . $name_pitch;
printf( "Element[\"\" \"%s\" \"IC1\" \"%s\" 0 0 %d %d 0 100 \"\"]\n(\n", $name, $name, mm2pcb( -$d_outline_x ), mm2pcb( $d_outline_y ) + 1000 );

for( my $i = 0; $i < $pins_x; $i++ ) {
  my $d = ($i - ($pins_x - 1) / 2) * $pin_dist;
  my $d1 = $d - $pin_width / 2;
  my $d2 = $d + $pin_width / 2;
  pad( $d1, $d_pins_outer_y, $d2, $d_pins_inner_y, $i + $pins_y + 1 );
  pad( -$d1, -$d_pins_outer_y, -$d2, -$d_pins_inner_y, $i + $pins_x + 2 * $pins_y + 1 );
}

for( my $i = 0; $i < $pins_y; $i++ ) {
  my $d = ($i - ($pins_y - 1) / 2) * $pin_dist;
  my $d1 = $d - $pin_width / 2;
  my $d2 = $d + $pin_width / 2;
  pad( -$d_pins_outer_x, $d1, -$d_pins_inner_x, $d2, $i + 1 );
  pad( $d_pins_outer_x, -$d1, $d_pins_inner_x, -$d2, $i + $pins_x + $pins_y + 1 );
}

line( -$d_corner_pins_x, -$d_corner_y, $d_corner_x, -$d_corner_y );
line( $d_corner_x, -$d_corner_y, $d_corner_x, $d_corner_y );
line( $d_corner_x, $d_corner_y, -$d_corner_x, $d_corner_y );
line( -$d_corner_x, $d_corner_y, -$d_corner_x, -$d_corner_pins_y );
line( -$d_corner_pins_x, -$d_corner_y, -$d_corner_x, -$d_corner_pins_y );

line( -$d_corner_x, -$d_outline_y, $d_outline_x, -$d_outline_y );
line( $d_outline_x, -$d_outline_y, $d_outline_x, $d_outline_y );
line( $d_outline_x, $d_outline_y, -$d_outline_x, $d_outline_y );
line( -$d_outline_x, $d_outline_y, -$d_outline_x, -$d_corner_y );
line( -$d_corner_x, -$d_outline_y, -$d_outline_x, -$d_corner_y );

print( "\t)\n" );