Listing 7

/*******************************************
**  Input Impedance Calculation           **
**                                        **
**  Maynard A. Wright, P. E. 1990         **
**                                        **
*******************************************/

/*  Stored as "zin.c." Algorithm used here
   described in M. A. Wright, "Computation of
   Input Impedance Using RPN Calculators," IEEE
   1979 Region VI Conference Proceedings. This
   version of the program uses functions from
   the Microsoft graphics library and must
   therefore be compiled using Microsoft C or QuickC.
   The program also uses function prototypes and
   constant definitions from include file cmplx.h
   and must be linked to library cmplxlib.lib. */

#include <graph.h>
#include <math.h>
#include <stdarg.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <local\cmplx.h>

#define DBSCALE 8.68588963 /*  convert dB to nepers */
#define PHASCALE 57.29577951 /*  convert degrees to
                            radians */
#define MINVAL 1e-100  /*  minimum value of double
                       input */
#define NW '\xC9' /*  northwest graphics corner */
#define NE '\xBB' /*  northeast graphics corner */
#define SW '\xC8' /*  southwest graphics corner */
#define SE '\xBC' /*  southeast graphics corner */
#define HZ '\xCD' /*  horizontal graphics line */
#define VR '\xBA' /*  vertical graphics line */

double get_real(char*, short, short);

void main(void)

{
   /*  declarations */
   
   char decision, counter;
   short linectr;
   double atten, phase, length;
   struct cmplx_nmbr calcz, termz, linez, inputz;
   
   /*  screen header */
   
   _settextcolor(14);
   _clearscreen(_GCLEARSCREEN);
   _settextposition(3,20);
   printf("%c", NW);
   for(counter = 1; counter <= 37; ++counter)
      printf("%c", HZ);
   printf("%c", NE);
   _settextposition(4,20);
   printf("%c INPUT IMPEDANCE CALCULATION     %c",
         VR, VR);
   _settextposition(5,20);
   printf("%c", SW);
   for(counter = 1; counter <= 37; ++counter)
      printf("%c", HZ);
   printf("%c", SE);
   
   /*  input data from keyboard */
   termz.real = get_real("ENTER REAL PART OF
TERMINATING IMPEDANCE IN OHMS:", 8, 17);
   if(termz.real == 0.) /*  make input nonzero to
                        avoid sub- */
      termz.real = MINVAL; /* sequent math errors */
   termz.imag = get_reat("ENTER IMAGINARY PART OF
TERMINATING IMPEDANCE IN OHMS:", 9, 12);
   if(termz.imag == 0.)
      termz.imag = MINVAL;
   do
   
   {
      linez.real = get_real("ENTER REAL PART OF
CHARACTERISTIC IMPEDANCE OF LINE IN OHMS:", 10, 6);
      If(linez.real == 0.)
         linez.real = MINVAL;
      linez.imag = get_real("ENTER IMAGINARY PART OF
CHARACTERISTIC IMPEDANCE OF LINE IN OHMS:", 11, 1);
      if(linez.imag == 0.)
         linez.imag = MINVAL;
      atten = get_real("ENTER ATTENUATION PER UNIT
LENGTH OF LINE:", 12, 24);
      if(atten == 0.)
         atten= MINVAL;
      _settextposition(13,22);
      printf("ATTENUATION IN DECIBELS OR NEPERS? ");
      printf("(D OR N):");
      do
      {
         fflush(stdin);
         decision = getche();
         if(decision != 'D' && decision != 'd' &&
              decision != 'N' && decision != 'n')
         {
            _settextposition(14,22);
            printf("      !!! RESPONSE MUST BE D OR
                  N !!!");
            printf("          ");
            _settextposition(13,66);
         }
      }
      while(decision != 'D' && decision != 'd' &&
            decision != 'N' && decision != 'n');
      if(decision == 'D' || decision == 'd')
         atten /= DBSCALE;
      phase = get_real("ENTER PHASE SHIFT PER UNIT
LENGTH OF LINE:", 14, 24);
      if(phase == 0.)
         phase = MINVAL;
      _settextposition(15,22);
      printf("PHASE SHIFT IN DEGREES OR RADIANS? ");
      printf("(D OR R):");
      do
      
      {
         fflush(stdin);
         decision = getche();
         if(decision != 'D' && decision != 'd' &&
              decision != 'R' && decision != 'r')
         {
            _settextposition(16,22);
            printf("      !!! RESPONSE MUST BE D OR
                  R !!!");
            printf("          ");
            _settextposition(15,66);
         }
      }
      while(decision != 'D' && decision != 'd' &&
           decision != 'R' && decision != 'r');
      if(decision == 'D' || decision == 'd')
         phase /= PHASCALE;
      length = get_real("ENTER
      
LENGTH OF LINE:", 16, 25);
      _settextposition(17,22);
      printf("
                ");
      if(length == 0.)
         length = MINVAL;
      
      /*  calculate attenuation and phase shift of line */
      
      atten *= length;
      phase *= length;
      
      /*  calculate termz / linez */
      
      calcz = cmplxdiv(termz, linez);
      
      /*  handle case of angle = 0 */
      
      if(calcz.imag == 0.)
         calcz.imag = 1e-100;
      
      /*  calculate inverse complex hyperbolic tangent */
      
      calcz = catnh(calcz);
      
      /*  add in line constants */
      
      calcz.real += atten;
      calcz.imag += phase;
      
      /*  calculate complex hyperbolic tangent */
      
      calcz = ctanh(calcz);
      
      /*  denormalize solution to obtain input impedance */
      
      inputz = cmplxmul(calcz, linez);
      
      /*  print results */
      
      for(linectr = 19; linectr <= 20; ++linectr)
      
      {
         _settextposition(linectr, 51);
         printf("                             ");
      }
      
      _settextposition(19,20);
      printf("REAL PART OF INPUT ");
      printf("IMPEDANCE = %+lG OHMS",inputz.real);
      _settextposition(20,15);
      printf("IMAGINARY PART OF INPUT ");
      printf("IMPEDANCE = %+lG OHMS\n\n",inputz.imag);
      
      /*  loop for another section or terminate execution */
      
      _settextposition(22,4);
      printf("USE INPUT IMPEDANCE AS TERMINAL IMPED");
      printf("ANCE FOR ANOTHER SECTION? ");
      _settextposition(22,67);
      decision = 0;
      fflush(stdin);
      decision = getche();
      if(decision == 'Y' || decision == 'y')
      
      {
         termz.real = inputz.real;
         termz.imag = inputz.imag;
         
         /*  set up screen for new input */
      
      for(linectr = 8; linectr <= 16; ++linectr)
      
      {
         _settextposition(linectr, 66);
         
         printf("                  ");
         }
         _settextposition(19,20);
         printf("                        ");
         printf("                        ");
         _settextposition(20,15);
         printf("                            ");
         printf("                        ");
         _settextposition(8,66);
         printf("%+lG", inputz.real);
         _settextposition(9,66);
         printf("%+lG", inputz.imag);
      }
   }
   
   while(decision == 'Y' || decision == 'y');
   printf("\n");
}

double get_real(char *num_string, short x, short y)

{
   struct rccoord rcoord;
   double value;
   char *phlag = '\0', *remainder, string[20];
   short inrow, incol;
   
   do
   
   {
      if(phlag)
      
      {
         _settextposition((x + 1), 1);
         printf("
                    ");
         printf("
                    ");
         _settextposition((x + 1), 25);
         printf("!!! ERROR IN INPUT: PLEASE REENTER
!!!");

      }
      
      _settextposition(x, y);
      printf("%s", num_string);
      printf("          ");
      rcoord = _gettextposition();
      inrow = rcoord.row;
      incol = rcoord.col + strlen(num_string);
      _settextposition(inrow, incol);
      ++phlag;
      fflush(stdin);
   }
   
   while((!(value = strtod((gets(string)),\
         &remainder)) && *remainder) || value ==
         HUGE_VAL);
   _settextposition(inrow, incol);
   printf("%G         ", value);
   if(phlag)
   
   {
      _settextposition((x+1), 25);
      printf("                                   ");
   }
   
   return(value);
}