#!/usr/local/bin/perl
#
#	gendetect.pl
#
#	Generate car detection circuit in Postscript.
#	This can then be used to generate an appropriate GIF for
#	inclusion.
#
#	We are working in a space of 8.5*72 x 11*72 which works
#	out to 612 x 792.  Remember that small values of Y are towards
#	the bottom of the page.
#

###
###	Constants
###
$TerminalRadius	= 5;		# Size of a terminal
$TwoPi		= 3.14159 * 2;	# A full revolution

###
###	Code
###

    print "%!\n";
    print "/Times-Roman findfont 12 scalefont setfont\n";
    print "0 0 0 setrgbcolor\n";

    for ($count = 0; $count < 4; $count++)
    	{
    	genblock(650, "LANE 1");
    	genblock(500, "LANE 2");
    	genblock(350, "LANE 3");
    	genblock(200, "LANE 4");
    	}

    # Put in the trim op-amp
    line(105, 750, 300, 750);
    line(300, 750, 300, 700);
    line(300, 700, 320, 700);
    line(320, 700, 350, 715);
    line(350, 715, 350, 685);
    line(350, 685, 320, 700);
    text(310, 705, "1");
    text(355, 695, "2");
    text(355, 715, "3");
    text(342, 690, "-");
    text(342, 705, "+");
    text(315, 720, "LM324");

    connection(310, 700);
    line(310, 700, 310, 675);
    line(310, 675, 360, 675);
    line(360, 675, 360, 690);
    line(360, 690, 350, 690);

    line(350, 710, 380, 710);
    line(380, 710, 375, 715);
    line(380, 710, 375, 705);
    line(385, 690, 385, 703);
    vresistor(385, 703, "10K");
    line(385, 718, 385, 730);
    plus5(385, 730);
    ground(385, 690);

    print "showpage\n";


###
###	genblock
###
###	Build a block for a specific lane
###
sub genblock
    {
    my($y, $title) = @_;
    my($neg, $pos, $out);

    # Build the sensor
    trans(30, $y + 20);
    line(15, $y + 30, 25, $y + 20);
    line(25, $y + 20, 25, $y + 25);
    line(15, $y + 25, 25, $y + 15);
    line(25, $y + 15, 22, $y + 15);

    # Build the second transistor
    line(43, $y + 28, 150, $y + 28);
    line(43, $y + 12, 50, $y + 12);
    trans(50, $y + 12);
    text(67, $y + 6, "E");
    text(67, $y + 22, "C");

    ground(63, $y + 4);

    # Build the connection up to +5
    line(63, $y + 20, 63, $y + 40);
    connection(63, $y + 28);
    vresistor(63, $y + 40, "100K");
    line(63, $y + 55, 63, $y + 65);
    plus5(63, $y + 65);

    # Put in the op-amp
    line(150, $y + 20, 150, $y + 50);
    line(150, $y + 50, 180, $y + 35);
    line(180, $y + 35, 150, $y + 20);
    text(153, $y + 28, "-");
    text(153, $y + 36, "+");
    text(155, $y + 10, "LM339");
    if ($title =~ /1/)
    	{
    	$neg = "4";
    	$pos = "5";
    	$out = "2";
    	}
    elsif ($title =~ /2/)
    	{
    	$neg = "6";
    	$pos = "7";
    	$out = "1";
    	}
    elsif ($title =~ /3/)
    	{
    	$neg = "8";
    	$pos = "9";
    	$out = "14";
    	}
    elsif ($title =~ /4/)
    	{
    	$neg = "10";
    	$pos = "11";
    	$out = "13";
    	}
    text(138, $y + 18, $neg);
    text(138, $y + 44, $pos);
    text(185, $y + 20, $out);

    # Output from op-amp
    line(180, $y + 35, 220 - $TerminalRadius, $y + 35);
    terminal(220, $y + 35);
    text(230, $y + 32, $title);

    # Trim line
    if ($title =~ /4/)
    	{
	line(105, $y + 100, 105, $y + 37);
    	}
    else
    	{
	line(105, $y + 100, 105, $y - 50);
	connection(105, $y + 37);
	}

    line(105, $y + 37, 115, $y + 37);
    hresistor(115, $y + 37, "10K");
    line(130, $y + 37, 150, $y + 37);
    connection(135, $y + 37);

    # Feedback loop
    connection(190, $y + 35);
    line(190, $y + 35, 190, $y + 60);
    line(135, $y + 60, 135, $y + 8);
    vresistor(135, $y - 7, "1M");
    ground(135, $y - 7);
    line(135, $y + 60, 145, $y + 60);
    hresistor(145, $y + 60, "1M");
    line(160, $y + 60, 190, $y + 60);

    # LED connection
    connection(200, $y + 35);
    line(200, $y + 5, 200, $y + 45);
    vresistor(200, $y + 45, "2.2K");
    line(200, $y + 60, 200, $y + 70);
    plus5(200, $y + 70);
    line(200, $y + 5, 210, $y + 5);
    hled(210, $y + 5);
    line(225, $y + 5, 235, $y + 5);
    hresistor(235, $y + 5, "1K");
    line(250, $y + 5, 260, $y + 5);
    line(260, $y + 5, 260, $y + 15);
    plus5(260, $y + 15);
    }


######
######	Primatives
######
######	This draws a number of different electrical symbols.
######

###
###	box
###
###	Draw a box
###
sub box
    {
    my($x1, $y1, $x2, $y2) = @_;

    print "newpath\n";
    print "$x1 $y1 moveto ";
    print "$x1 $y2 lineto ";
    print "$x2 $y2 lineto ";
    print "$x2 $y1 lineto ";
    print "closepath stroke\n";
    }


###
###	connection
###
###	Drawn a filled circle at a specified point.
###
sub connection
    {
    my($x, $y) = @_;
    my($rad);

    print "newpath\n";
    $rad = $TerminalRadius - 2;
    print "$x $y $rad 0 360 arc fill\n";
    }


###
###	ground
###
###	Drawn a ground terminal.
###
sub ground
    {
    my($x, $y) = @_;

    line($x, $y, $x, $y - 15);
    $y -= 15;
    line($x - 8, $y, $x + 8, $y);
    line($x - 6, $y - 3, $x + 6, $y - 3);
    line($x - 4, $y - 6, $x + 4, $y - 6);
    }


###
###	hdiode
###
###	Place a horizontal diode.
###
sub hdiode
    {
    my($x, $y, $title) = @_;
    my($length, $height);

    $length = 15;
    $height = 7;

    print "newpath\n";
    printf "%d %d moveto ", $x, $y - $height;
    printf "%d %d lineto ", $x, $y + $height;
    printf "%d %d lineto ", $x + $length, $y;
    print "closepath fill\n";

    printf "%d %d moveto ", $x + $length, $y - $height;
    printf "%d %d lineto ", $x + $length, $y + $height;
    print "stroke\n";

    text($x - 5, $y + 10, $title);
    }


###
###	hresistor
###
###	Add a horizontal resistor going up from the
###	given point.  The size is 15 points.
###
sub hresistor
    {
    my($x, $y, $title) = @_;

    line($x, $y, $x + 3, $y + 3);
    line($x + 3, $y + 3, $x + 6, $y - 3);
    line($x + 6, $y - 3, $x + 9, $y + 3);
    line($x + 9, $y + 3, $x + 12, $y - 3);
    line($x + 12, $y - 3, $x + 15, $y);
    text($x - 5, $y + 6, $title);
    }


###
###	hled
###
###	Place a horizontal led.
###
sub hled
    {
    my($x, $y) = @_;
    my($length, $height);

    $length = 15;
    $height = 7;

    print "newpath\n";
    printf "%d $y 7.5 0 360 arc stroke\n", $x + 7.5;
    line($x, $y, $x + 15, $y);
    line($x + 3, $y + 4, $x + 3, $y - 4);
    line($x + 3, $y, $x + 10, $y + 6);
    line($x + 10, $y + 6, $x + 10, $y - 6);
    line($x + 10, $y - 6, $x + 3, $y);

    line($x + 3, $y + 10, $x + 5, $y + 14);
    line($x + 5, $y + 14, $x + 2, $y + 12);
    line($x + 6, $y + 10, $x + 8, $y + 14);
    line($x + 8, $y + 14, $x + 9, $y + 12);
    }


###
###	line
###
###	Draw a line between two x/y points.
###
sub line
    {
    my($x1, $y1, $x2, $y2) = @_;

    print "$x1 $y1 moveto $x2 $y2 lineto stroke\n";
    }


###
###	plus5
###
###	Draw an arrow and +5 at the given point.
###
sub plus5
    {
    my($x, $y) = @_;

    line($x, $y, $x - 3, $y - 3);
    line($x, $y, $x + 3, $y - 3);
    text($x, $y + 3, "+5V");
    }


###
###	terminal
###
###	Drawn an empty circle at a specified point.
###
sub terminal
    {
    my($x, $y) = @_;

    print "newpath\n";
    print "$x $y $TerminalRadius 0 360 arc stroke\n";
    }


###
###	text
###
###	Draw text in the page
###
sub text
    {
    my($x, $y, $text) = @_;

    print "$x $y moveto ($text) show\n";
    }


###
###	trans
###
###	Write a transistor.
###
sub trans
    {
    my($x, $y) = @_;

    line($x, $y + 8, $x, $y - 8);		# Draw vertical line
    line($x, $y + 2, $x + 13, $y + 8);
    line($x, $y - 2, $x + 13, $y - 8);

    # This isn't perfect
    print "newpath\n";
    printf "%d %d moveto ", $x + 5, $y - 1;
    printf "%d %d lineto ", $x + 12, $y - 7;
    printf "%d %d lineto ", $x + 3, $y - 7;
    print "closepath fill\n";
    }


###
###	vcap
###
###	Draw a capacitor along a vertical axis.
###	Right now, $y1 should be > $y2.
###
sub vcap
    {
    my($x1, $y1, $y2, $label1, $label2, $label3) = @_;
    my($mid);

    $mid = ($y1 + $y2) / 2 + 3;
    line($x1, $y1, $x1, $mid);
    line($x1 - 8, $mid, $x1 + 8, $mid);
    $mid -= 6;
    line($x1 - 8, $mid, $x1 + 8, $mid);
    line($x1, $mid, $x1, $y2);
    text($x1 + 3, $mid + 12, $label1) if ($label1 ne "");
    text($x1 + 12, $mid + 0, $label2) if ($label2 ne "");
    text($x1 + 3, $mid - 3, $label3) if ($label3 ne "");
    }


###
###	vresistor
###
###	Add a vertical resistor going up from the
###	given point.  The size is 15 points.
###
sub vresistor
    {
    my($x, $y, $title) = @_;

    line($x, $y, $x - 3, $y + 3);
    line($x - 3, $y + 3, $x + 3, $y + 6);
    line($x + 3, $y + 6, $x - 3, $y + 9);
    line($x - 3, $y + 9, $x + 3, $y + 12);
    line($x + 3, $y + 12, $x, $y + 15);
    text($x + 5, $y + 6, $title);
    }
