#!/usr/bin/env perl

## 555 Timer IC pulse width solver

## This file Copyright 2000 <contact@gbppr.org> under the GPL
## NO WARRANTY. Please send bug reports / patches / reports.

sub Time {
undef $_; undef $tim; undef $unit;
while (!m/^([0-9.]+)(u|U|m|M|s|S+)$/) {
	print "\nu = microseconds\n".
              "m = milliseconds\n".
              "s = just seconds\n\n".
              "Enter $T  [value][u,m,s]: ";
	chomp($_ = <STDIN>); 

	if (m/^([0-9.]+)(u|U|m|M|s|S+)$/) {
		$tim = $1;
		$unit = $2;
	}

	if ($unit =~ /u/i) {
		$t = $tim / 1000000;
	}

	elsif ($unit =~ /m/i) {
		$t = $tim / 1000;
	}

	elsif ($unit =~ /s/i) {
		$t = $tim;
	}
 }
}

sub Cap {
undef $_; undef $c; undef $unit;
while (!m/^([0-9.]+)(u|U|p|P|n|N+)$/) {
	print "\nu = microfarads\n".
      	      "n = nanofarads\n".
              "p = picofarads\n\n".
              "Enter value of C1  [value][u,n,p]: ";
	chomp($_ = <STDIN>);

	if (m/^([0-9.]+)(u|U|p|P|n|N+)$/) {
		$c = $1;
		$unit = $2;
	}

	if ($unit =~ /u/i) {
		$c1 = $c / 1000000;
	}

	elsif ($unit =~ /n/i) {
		$c1 = $c / 1000000000;
	}

	elsif ($unit =~ /p/i) {
		$c1 = $c / 1000000000000;  
	}
 }
}

sub Res {
undef $_; undef $r; undef $unit;
while (!m/^([0-9.]+)(k|K|m|M+)$/) {
	print "\nk = kilohms\n".
      	      "M = megaohms\n\n".
              "Enter value of $R  [value][k,M]: ";
	chomp($_ = <STDIN>); 

	if (m/^([0-9.]+)(k|K|m|M+)$/) {
		$r = $1;
		$unit = $2;
	}

	if ($unit =~ /k/i) {
		$r1 = $r * 1000;
	}

	elsif ($unit =~ /m/i) {
		$r1 = $r * 1000000;
	}                              
 }
}

sub Mono {
print  "\33[H\33[J".
       "    +----------+---+----> Vcc (5 to 15 VDC)           \n".
       "    |       ___|___|___                               \n".       
       "   < >  R1  |  8   4  |             Monostable pulse  \n".
       "   < >      |         | Output        ______          \n".
       "    |       |        3+----->      ___|    |____      \n".
       "    |-------+7        |                               \n".
       "    |-------+6  555   |                < t >          \n".
       "    |       |   timer |                               \n".
       " C1 -   +---+2        |                               \n".
       "    -   |   |         |                               \n";
printf "    |    \\  |         |       t  = %.6f microseconds \n",$tu;
printf "    |   |   |         |            %.6f milliseconds  \n",$tm;
printf "    |   |   |        1+--+    R1 = %.3f kilohms       \n",$r1k;
printf "    |   |   |__5______|  |    C1 = %.6f uF (%.3f pF)  \n",$c1u,$c1p;
print  "    |   |      |         |                            \n".
       "    |   |      - 0.01 uF |                            \n".
       "    |   |      -         |                            \n".
       "    |   |      |         |                            \n".
       "    +---+------+---------+---> Ground                 \n";
}

sub Astable {
print  "\33[H\33[J".
       "    +----------+---+----> Vcc (5 to 15 VDC)           \n".
       " R1 |       ___|___|___                               \n".
       "   < >      |  8   4  |             Astable pulse     \n".
       "   < >      |         | Output     _____   _____      \n".
       "    |       |        3+----->    __|   |___|   |__    \n". 
       " R2 +-------+7        |            <t1> <t2>          \n".
       "   < >      |   555   |                               \n".
       "   < >      |   timer |                               \n";
printf "    +----+--+2        |       R1 = %.3f kilohms       \n",$r1k;
printf "    |    |  |         |       R2 = %.3f kilohms       \n",$r2k;
printf " C1 -    +--+6        |       C1 = %.6f uF (%.3f pF)  \n",$c1u,$c1p;  
print  "    -       |         |                               \n"; 
printf "    |       |        1+--+    t1 = %.6f microseconds  \n",$t1u,;
printf "    |       |__5______|  |         %.6f milliseconds  \n",$t1m;
printf "    |          |         |    t2 = %.6f microseconds  \n",$t2u,;
printf "    |          - 0.01 uF |         %.6f milliseconds  \n",$t2m;
printf "    |          -         |  Freq = %.6f kHz           \n",$freq;
print  "    |          |         |                            \n".
       "    +----------+---------+---> Ground                 \n";
}         

sub Calc {
$tu   = $t * 1000000;
$tm   = $t * 1000;
$t1u  = $t1 * 1000000;
$t1m  = $t1 * 1000;
$t2u  = $t2 * 1000000;
$t2m  = $t2 * 1000;
$r1k  = $r1 / 1000;
$r2k  = $r2 / 1000;
$c1u  = $c1 * 1000000;
$c1p  = $c1 * 1000000000000;
$freq = $freq / 1000;
}

while (!$ans || $ans > 2 || $ans =~ m/[a-z]/i) {
	print "\n\n\t\t555 Timer IC Pulse Width Circuit Solver\n\n".
      	      "1) Monostable\n".
              "2) Astable\n\n".
              "Enter your selection: ";
	chomp($ans = <STDIN>);
}

if ($ans == 1) {

	&Mono;
	
	while (!$sel || $sel > 3 || $sel =~ m/[a-z]/i) {
		print "\n1) Calculate t    (given R1 and C1)\n".
      	              "2) Calculate R1   (given t and C1)\n".
                      "3) Calculate C1   (given t and R1)\n\n".
                      "Enter your selection: ";
		chomp($sel = <STDIN>);
	}

	if ($sel == 1) {

		&Res($R = "R1");
		&Cap;
		$t = ($r1 * $c1);
		&Calc;
		&Mono;
		print "\n";
        }

	elsif ($sel == 2) {

		&Mono;
		&Time($T = "t");
		&Cap;
		$r1 = $t / $c1;
		&Calc;
		&Mono;
		print "\n";
        }

	elsif ($sel == 3) {

		&Mono;
		&Time($T = "t");
		&Res($R = "R1");         
		$c1 = $t / $r1;
		&Calc;
		&Mono;
		print "\n";
        }
}

elsif ($ans == 2) {

	&Astable;

	while (!$sel || $sel > 4 || $sel =~ m/[a-z]/i) {
		print "\n1) Calculate t1 and t2  (given R1, R2 and C1)\n".
                      "2) Calculate R1         (given t1, C1 and R2)\n".
                      "3) Calculate R2         (given t1, t2 and C1)\n".
                      "4) Calculate C1         (given t1, t2 and R2)\n\n".
                      "Enter your selection: ";
		chomp($sel = <STDIN>);
	}  

	if ($sel == 1)  {

		&Astable;
		&Res($R = "R1");
		$r1a = $r1;
		&Res($R = "R2");
		$r2 = $r1;
		$r1 = $r1a;
		&Cap;
		$t1 = ((0.693 * ($r1 + $r2)) * $c1);
		$t2 = 0.693 * $r2 * $c1;
		$freq = 1.44 / (((2 * $r2) + $r1) * $c1);
		&Calc;
		&Astable;
		print "\n";
        }

	elsif ($sel == 2) {

		&Astable;
		&Time($T = "t1");
		$t1 = $t;
		&Cap;
		&Res($R = "R2");
		$r2 = $r1;
		$t2 = 0.693 * $r2 * $c1;
		$r1 = ($t1 / (0.693 * $c1)) - $r2;
		$freq = 1.44 / (((2 * $r2) + $r1) * $c1);
		&Calc;
		&Astable;
		print "\n";

	}

	elsif ($sel == 3) {

		&Astable;
		&Time($T = "t1");
		$t1 = $t;
		&Time($T = "t2");
		$t2 = $t;
		&Cap;
		$r2 = $t2 / (0.693 * $c1);
		$r1 = $t1 / (0.693 * $c1) - $r2;
		$freq = 1.44 / (((2 * $r2) + $r1) * $c1);
		&Calc;
		&Astable;
		print "\n";

	}

	elsif ($sel == 4) {

		&Astable;
		&Time($T = "t1");
		$t1 = $t;
		&Time($T = "t2");
		$t2 = $t; 
		&Res($R = "R2");
		$r2 = $r1;
		$c1 = $t2 / ($r2 * 0.693);
		$r2 = $t2 / (0.693 * $c1);
		$r1 = ($t1 / (0.693 * $c1)) - $r2;
		$freq = 1.44 / (((2 * $r2) + $r1) * $c1);
		&Calc;
		&Astable;
		print "\n";

 	}
}
