! The Fortran 90 Version
! Physics 222
! Professor: Jim. Crumley
! Characteristics of Transistor Amplifier
! Written March 14, 07
! Poa Xuan Yeap
! Transistor Amplifier Circuit
! This program will show the different characteristics of transistor amplifier and their affect on the voltage gain.

!The expression used and their units:
!i_c - The current in the output side, being called as output current here. The collector side of the transistor (AMP).
!i_b - The current in the input side, being called as input current here. The base side of the transistor (AMP).
!r_b - The base resistor, the resistor in the circuit at the base side of the transistor (Ohm).
!r_c - The collector resistor, the resistor in the circuit at the collector side of the transistor (ohm).
!r_e - The emitter resistor, the resistor in the circuit at the emitter side of the transistor (ohm).
!beta - The current gain, beat=i_b/i_c
!a_v - The voltage gain, there are more than one formulas used here for voltage gain (Volt).
!v_s - The source voltage (Volt).

!jc  Good header comment.

PROGRAM transistor_amplifiers

  IMPLICIT NONE
  CHARACTER::options

!The list of all options for looking at the characteristics in the transistor amplifier

!jc  You should really say what units you want input values in when
!jc  you ask for input.

  PRINT*,'  '
  PRINT*,'This program will show the different characteristics of transistor amplifier.'
  PRINT*,'It will show the affects of each piece in transistor amplifier circuit on the voltage gain.'
  PRINT*,'Make an option of which you will like to calculate and see its affect on the voltage gain.'
  !jc  For this portion you should make it clear where the graphed data is
  !jc  coming from - I expected to be asked for a filename.

  PRINT*,'  '
  PRINT*,'Option A:'
  PRINT*,'  It will read in list of input and output currents from a file with any number of data.'
  PRINT*,'  Then it will calculate the current gain (beta) and voltage gain with some given values of resistor.'
  PRINT*,'  It will also graph the relationship between curretn and voltage gain.'
  PRINT*,'Option B:'
  PRINT*,'  It will show the relationship between the output current and the voltage gain.'
  PRINT*,'  It will calculate the output current with a list of voltage gain from 1 to 100 with increment of 5.'
  PRINT*,'Option C:'
  PRINT*,'  Similar as option B, but it will only calculate the output current with a specific voltage gain.'
  PRINT*,'Option D:'
  PRINT*,'  It will show the relationship between the source voltage and the voltage gain.'
  PRINT*,'  It will calculate the voltage gain with a list of source voltage from 1 to 100 with increment of 5.'
  PRINT*,'Option E:'
  PRINT*,'  Similar as option D, but it will only calculate the voltage gain with a specific source voltage.'
  PRINT*,'Option F:'
  PRINT*,'  It will show the relationship between the current gain and the voltage gain.'
  PRINT*,'  It will calculate the voltage gain with a list of current gain from 1 to 100 with increment of 5.'
  PRINT*,'Option G:'
  PRINT*,'  Similar as option D, but it will only calculate the voltage gain with a specific current gain.'
  PRINT*,'Option H:'
  PRINT*,'  It will show the relationship between the collector resistor and voltage gain as well as the current gain.'
  PRINT*,'  It will calculate the collector resistor with a list of voltage gain and current gain.'
  PRINT*,'  The voltage gain and current gain will range from 10 to 100 with the increment of 10.'
  PRINT*,'Option I:'
  PRINT*,'  Similar as option H.'
  PRINT*,'  However, it will only calculate the collector resistor with specific voltage gain and current gain.'
  PRINT*,'Option J:'
  PRINT*,'  It will show the relationship between the base resistor and voltage gain as well as the current gain.'
  PRINT*,'  It will calculate the base resistor with a list of voltage gain and current gain.'
  PRINT*,'  The voltage gain and current gain will range from 10 to 100 with the increment of 10.'
  PRINT*,'Option K:'
  PRINT*,'  Similar as option J.'
  PRINT*,'  However, it will only calculate the base resistor with specific voltage gain and current gain.'
  PRINT*,'Option L:'
  PRINT*,'  It will show the relationship between the emitter resistor and voltage gain as well as the current gain.'
  PRINT*,'  It will calculate the emitter resistor with a list of voltage gain and current gain.'
  PRINT*,'  The voltage gain and current gain will range from 10 to 100 with the increment of 10.'
  PRINT*,'Option M:'
  PRINT*,'  Similar as option L.'
  PRINT*,'  However, it will only calculate the emitter resistor with specific voltage gain and current gain.'
  PRINT*,'  '
  PRINT*,'PLEASE MAKE YOUR CHOICE IN CAPITALIZED ALPHABET BETWEEN A AND M:'
  READ*,options
  PRINT*,'  '

!all the options, each will call out a specific subroutine
    transistor_amplifier: SELECT CASE (options)
    CASE ('A')
      CALL currents_table ('*')
    CASE ('B')
      CALL output_current_1
    CASE ('C')
      CALL output_current_2
    CASE ('D')
      CALL voltage_gain_1
    CASE ('E')
      CALL voltage_gain_2
    CASE ('F')
      CALL voltage_gain_3
    CASE ('G')
      CALL voltage_gain_4
    CASE ('H')
      CALL collector_resistor_1
    CASE ('I')
      CALL collector_resistor_2
    CASE ('J')
      CALL base_resistor_1
    CASE ('K')
      CALL base_resistor_2
    CASE ('L')
      CALL emitter_resistor_1
    CASE ('M')
      CALL emitter_resistor_2
    CASE DEFAULT
      PRINT*,'It is not an option!!'
    END SELECT transistor_amplifier

  PRINT*,'  ' !print out a space

END PROGRAM transistor_amplifiers

SUBROUTINE currents_table (format_code)

  IMPLICIT NONE
  CHARACTER(*)::filename="currents.txt" !storing the file in filename.
  CHARACTER(*)::format_code
  REAL::i_b(50),i_c(50),beta(50),a_v(50)
  REAL::r_b,r_c,r_e
  INTEGER::i_stat,status,ier,pgbeg,i,n

  PRINT*,'Please enter the values for your base resistor, collector resistor and emitter resistor.'
  PRINT*,'  ' !print out a space
  PRINT*,'Base Resistor:'
  READ*,r_b
  PRINT*,'Collector Resistor:'
  READ*,r_c
  PRINT*,'Emitter Resistor:'
  READ*,r_e
  PRINT*,'number of data'
  READ*,n
  PRINT*,'  ' !print out a space

  OPEN (2,FILE=filename,STATUS='old',ACTION='read',IOSTAT=status) !This will open the file read-only.
  i_stat=0

  PRINT*,'Results:'
  PRINT*,' Input Current   Output Current   Current Gain    Voltage Gain'

  DO WHILE (i_stat==0)  !this loop will create a table from the data in the file opened.
    DO i=1,n
      IF (format_code=='*') THEN
        READ (2,*,IOSTAT=i_stat) i_b(i),i_c(i)
      END IF
      IF (i_stat/=0) THEN
        PRINT*,'IOSTAT is',i_stat
        EXIT
      END IF
        beta(i)=i_b(i)/i_c(i)  !calculate the current gain from the input and output currents.
        a_v(i)=beta(i)*(r_c/(r_b+((1+beta(i))*r_e)))  !calculate the voltage gain from the data input.
        PRINT '(4("|",f15.3),"|")',i_b(i),i_c(i),beta(i),a_v(i)
    END DO
  END DO

  !graph of beta and voltage gain
  ier = pgbeg(0,'?',1,1) !giving choices on where to print out the graph
  IF (ier.ne.1) STOP
  CALL pgenv(beta(1),beta(n),a_v(1),a_v(n),0,0)  
  !x ranges from 0 to the last value of collector current and y ranges from 0 to the last value of voltage gain
  CALL pglab('Current Gain (Beta)','Voltage Gain (volt)',&
  'Relationship between collector current and voltage gain')
  CALL pgpt(n,beta(1:n),a_v(1:n),8)
  CALL pgend


END SUBROUTINE currents_table

SUBROUTINE output_current_1

!jc  It is a good idea to put the purpose of a subroutine at the top of the
!jc  subroutine.

  IMPLICIT NONE
  INTEGER::i,j
  REAL::i_c(100)
  real::v_s,r_c
  REAL,DIMENSION(1:100)::a_v=(/(i,i=1,100)/)  !list of voltage gain from 1 to 100.

  PRINT*,'Please enter the value for source voltage and collector resistor.'
  PRINT*,'  ' !print out a space
  PRINT*,'source voltage:'
  READ*,v_s
  PRINT*,'collector resistor:'
  READ*,r_c
  PRINT*,'  ' !print out a space
  PRINT*,'Results:'
  PRINT*,' Voltage Gain     Output Current'

!jc  Why is this indented more than the print lines?

      i_c(1)=0  !initializing the collector current, with initial value as zero instead one 1
      a_v(1)=0  !initializing the voltage gain, with initial value as zero instead one 1
      DO j=5,100,5
        output_currents: DO i=1,100
                           i_c(i)=(a_v(i)*v_s)/r_c
                           !calculating the output current with the list of voltage gain.
                         END DO output_currents
        PRINT '(2("|"F16.3)"|")',a_v(j),i_c(j)
      END DO

END SUBROUTINE output_current_1

SUBROUTINE output_current_2

  IMPLICIT NONE
  REAL::i_c,v_s,r_c,a_v

  PRINT*,'Please enter the value for source voltage, collector resistor and voltage gain.'
  PRINT*,'  ' !print out a space
  PRINT*,'source voltage:'
  READ*,v_s
  PRINT*,'collector resistor:'
  READ*,r_c
  PRINT*,'voltage gain'
  READ*,a_v !print out a space
  PRINT*,'  '

      i_c=(a_v*v_s)/r_c  !calculating the ouput current with a specific voltage gain.
      PRINT*,'Results:'
      PRINT*,'Voltage Gain:',a_v
      PRINT*,'Output Current:',i_c

END SUBROUTINE output_current_2

SUBROUTINE voltage_gain_1

  IMPLICIT NONE
  INTEGER::i,j
  REAL::i_c,r_c,v_c
  REAL::a_v(100)
  REAL,DIMENSION(1:100)::v_s=(/(i,i=1,100)/)  !list of source voltage from 1 to 100.

  PRINT*,'Please enter the value for Output Current and Collector Resistor.'
  PRINT*,'  ' !print out a space
  PRINT*,'Output Current:'
  READ*,i_c
  PRINT*,'Collector Resistor:'
  READ*,r_c
  PRINT*,'  ' !print out a space
  PRINT*,'Results:'
  PRINT*,' Source Voltage   Voltage Gain'

      a_v(1)=0  !initializing voltage gain, with initial value as zero instead of 1.
      v_s(1)=0  !initializing source voltage, with initial value as zero instead of 1.
      v_c=i_c/r_c  !calculating the input voltage from the input current and input resistor
      DO j=5,100,5
        voltage_gain: DO i=1,100
                         a_v(i)=v_c/v_s(i)
                         !calculating voltage gain with input volrage and list of source voltage.
                      END DO voltage_gain
          PRINT '(2("|"F16.3)"|")',v_s(j),a_v(j)
      END DO

END SUBROUTINE voltage_gain_1

SUBROUTINE voltage_gain_2

  IMPLICIT NONE
  REAL::a_v,i_c,r_c,v_s,v_c

  PRINT*,'Please enter the value for output current, collector resistor and source voltage.'
  PRINT*,'  ' !print out a space
  PRINT*,'Output Current:'
  READ*,i_c
  PRINT*,'Collector Resistor:'
  READ*,r_c
  PRINT*,'Source Voltage:'
  READ*,v_s
  PRINT*,'  ' !print out a space

      v_c=i_c/r_c  !calculating the input voltage from the input current and input resistor
      a_v=v_c/v_s  !calculating the voltage gain from the input and output volrage.

        PRINT*,'Results:'
        PRINT*,'Source Voltage:',v_s
        PRINT*,'Voltage Gain:',a_v

END SUBROUTINE voltage_gain_2

SUBROUTINE voltage_gain_3

  IMPLICIT NONE
  INTEGER::i,j
  REAL::r_b,r_c,r_e
  REAL::a_v(100)
  REAL,DIMENSION(1:100)::beta=(/(i,i=1,100)/)

  PRINT*,'Please enter the value for base resistor, collector resistor and emitter resistor.'
  PRINT*,'  ' !print out a space
  PRINT*,'Base Resistor:'
  READ*,r_b
  PRINT*,'Collector Resistor:'
  READ*,r_c
  PRINT*,'Emitter Resistor:'
  READ*,r_e
  PRINT*,'  ' !print out a space
  PRINT*,'Results:'
  PRINT*,' Current Gain    Voltage Gain'

      a_v(1)=0  !initializing voltage gain, with initial value as zero instead of 1.
      beta(1)=0  !initializing current gain, with initial value as zero instead of 1.
!jc  You could simplify this and many of the other calculations 
!jc  using array syntax.
      DO j=5,100,5
        currents_gain: DO i=1,100
                          a_v(i)=beta(i)*(r_c/(r_b+((1+beta(i))*r_e))) 
                          !calculating voltage gain with a list of current gain
                        END DO currents_gain
          PRINT '(2("|"F15.3)"|")',beta(j),a_v(j)
      END DO

END SUBROUTINE voltage_gain_3

SUBROUTINE voltage_gain_4

  IMPLICIT NONE
  REAL::a_v,r_b,r_c,r_e,beta

  PRINT*,'Please enter the value for base resistor, collector resistor, emitter resistor and beta.'
  PRINT*,'  ' !print out a space
  PRINT*,'Base Resistor:'
  READ*,r_b
  PRINT*,'Collector Resistor:'
  READ*,r_c
  PRINT*,'Emitter Resistor:'
  READ*,r_e
  PRINT*,'Current Gain (beta):'
  READ*,beta
  PRINT*,'  ' !print out a space

      a_v=beta*(r_c/(r_b+((1+beta)*r_e))) 
      ! calculating the voltage gain with a specific current gain

        PRINT*,'Results:'
        PRINT*,'Current Gain (beta):',beta
        PRINT*,'Voltage Gain:',a_v

END SUBROUTINE voltage_gain_4

SUBROUTINE collector_resistor_1

  IMPLICIT NONE
  INTEGER::i,j
  REAL::r_b,r_e
  REAL,DIMENSION(1:100)::a_v=(/(i,i=1,100)/)
  REAL,DIMENSION(1:100)::beta=(/(j,j=1,100)/)
  REAL,DIMENSION(1:100,1:100)::r_c

  PRINT*,'Please enter the value for base resistor and emitter resistor'
  PRINT*,'  ' !print out a space
  PRINT*,'Base Resistor:'
  READ*,r_b
  PRINT*,'Emitter Resistor:'
  READ*,r_e
  PRINT*,'  ' !print out a space
  PRINT*,'Current Gain is in the column and Voltage Gain is in the row.'

      a_v(1)=0   !initializing voltage gain, with initial value as zero instead of 1.
      beta(1)=0  !initializing current gain, with initial value as zero instead of 1.

      PRINT*,'Results:'
      PRINT '("          ",11F10.2)',beta(10:100:10)

      votlage_gain: DO i=10,100,10
          current_gain: DO j=1,100
            r_c(i,j)=(a_v(i)*(r_b+(1+beta(j))*r_e))/beta(j)
            ! calculating a list of collector resistor with list of current gain
          END DO current_gain
            IF (r_c(i,j)<0.) THEN
            !jc  Good error checking
              !preventing a negative value of the collector resistor
              !only print out a positive value of the collector resistor
              PRINT*,'ERROR: The collector resistor has to be bigger or equal to zero!'
              PRINT*,'PLEASE ENTER A NEW SET OF VALUE!!'
            ELSE
              PRINT '(50F10.2)',a_v(i),r_c(i,10:100:10) !print out the table
            END IF
      END DO votlage_gain

END SUBROUTINE collector_resistor_1

SUBROUTINE collector_resistor_2

  IMPLICIT NONE
  REAL::r_b,r_c,r_e,a_v,beta

  PRINT*,'Please enter the value for base resistor, emitter resistor, voltage gain and current gain'
  PRINT*,'  ' !print out a space
  PRINT*,'Base Resistor:'
  READ*,r_b
  PRINT*,'Emitter Resistor:'
  READ*,r_e
  PRINT*,'Coltage Gain:'
  READ*,a_v
  PRINT*,'Current Gain (beta):'
  READ*,beta
  PRINT*,'  ' !print out a space

          r_c=(a_v*(r_b+(1+beta)*r_e))/beta !calculating for the collector resistor with a specific current gain.

          IF (r_c<0.) THEN
            !preventing a negative value of collector resistor
            !only print out a possible value of collector resistor
            PRINT*,'ERROR: The collector resistor has to be bigger or equal to zero!'
            PRINT*,'PLEASE ENTER A NEW SET OF VALUE!!'
          ELSE
            PRINT*,'Results:'
            PRINT*,'Voltage Gain:',a_v
            PRINT*,'Current Gain (beta):',beta
            PRINT*,'Collector Resistor:',r_c
          END IF

END SUBROUTINE collector_resistor_2

SUBROUTINE base_resistor_1

  IMPLICIT NONE
  INTEGER::i,j
  REAL::r_c,r_e
  REAL,DIMENSION(1:100)::a_v=(/(i,i=1,100)/)
  REAL,DIMENSION(1:100)::beta=(/(j,j=1,100)/)
  REAL,DIMENSION(1:100,1:100)::r_b

  PRINT*,'Please enter the value for collector resistor and emitter resistor.'
  PRINT*,'  ' !print out a space
  PRINT*,'Collector Resistor:'
  READ*,r_c
  PRINT*,'Emitter Resistor:'
  READ*,r_e
  PRINT*,'  ' !print out a space
  PRINT*,'Current Gain is in the column and Voltage Gain is in the row.'

      a_v(1)=0   !initializing voltage gain, with initial value as zero instead of 1.
      beta(1)=0   !initializing current gain, with initial value as zero instead of 1.

      PRINT*,'Results:'
      PRINT '("          ",11F10.2)',beta(10:100:10)

      votlage_gain: DO i=10,100,10
          current_gain: DO j=1,100
            r_b(i,j)=((beta(j)*r_c)-(a_v(i)*(1+beta(j))*r_e))/a_v(i)
            !calculate the table of base resistor with list of votlage gain and current gain
          END DO current_gain
            IF (r_b(i,j)<0.) THEN
              !print only the positive base resistor
              PRINT*,'ERROR: The base resistor has to be bigger or equal to zero!'
              PRINT*,'PLEASE ENTER A NEW SET OF VALUE!!'
            ELSE
              PRINT '(50F10.2)',a_v(i),r_b(i,10:100:10) !print out the talbe of base resistor
            END IF
      END DO votlage_gain

END SUBROUTINE base_resistor_1

SUBROUTINE base_resistor_2

  IMPLICIT NONE
  REAL::r_b,r_c,r_e,a_v,beta

  PRINT*,'Please enter the value for collector resistor, emitter resistor, votlage gain and current gain'
  PRINT*,'  ' !print out a space
  PRINT*,'Collector Resistor:'
  READ*,r_c
  PRINT*,'Emitter Resistor:'
  READ*,r_e
  PRINT*,'Voltage Gain:'
  READ*,a_v
  PRINT*,'Current Gain (beta):'
  READ*,beta
  PRINT*,'  ' !print out a space

          r_b=((beta*r_c)-(a_v*(1+beta)*r_e))/a_v
          !calcualte a specific base resistor with specific boltage and current gain

          IF (r_b<0.) THEN
            !print out only the positive value of base resistor
            PRINT*,'ERROR: The base resistor has to be bigger or equal to zero!'
            PRINT*,'PLEASE ENTER A NEW SET OF VALUE!!'
          ELSE
            PRINT*,'Results:'
            PRINT*,'Voltage Gain:',a_v
            PRINT*,'Current Gain (beta):',beta
            PRINT*,'Base Resistor:',r_b
          END IF

END SUBROUTINE base_resistor_2

SUBROUTINE emitter_resistor_1

  IMPLICIT NONE
  INTEGER::i,j
  REAL::r_b,r_c
  REAL,DIMENSION(1:100)::a_v=(/(i,i=1,100)/)
  REAL,DIMENSION(1:100)::beta=(/(j,j=1,100)/)
  REAL,DIMENSION(1:100,1:100)::r_e

  PRINT*,'Please enter the value for base resistor and collector resistor.'
  PRINT*,'  ' !print out a space
  PRINT*,'Base Resistor:'
  READ*,r_b
  PRINT*,'Collector Resistor:'
  READ*,r_c
  PRINT*,'  ' !print out a space
  PRINT*,'Current Gain is in the column and Voltage Gain is in the row.'

      a_v(1)=0   !initializing voltage gain, with initial value as zero instead of 1.
      beta(1)=0   !initializing current gain, with initial value as zero instead of 1.

      PRINT*,'Results:'
      PRINT '("          ",11F10.2)',beta(10:100:10)

      votlage_gain: DO i=10,100,10
          current_gain: DO j=1,100
            r_e(i,j)=((beta(j)*r_c)-(a_v(i)*r_b))/(a_v(i)*(1+beta(j)))
            !calculate table of emitter resistor with list of voltage and current gain.
          END DO current_gain
            IF (r_e(i,j)<0.) THEN
              !in order to print out only the positive value of emitter resistor.
              PRINT*,'ERROR: The emitter resistor has to be bigger or equal to zero!!'
              PRINT*,'PLEASE ENTER A NEW SET OF VALUE!!'
            ELSE
              PRINT '(50F10.2)',a_v(i),r_e(i,10:100:10)
            END IF
      END DO votlage_gain

END SUBROUTINE emitter_resistor_1

SUBROUTINE emitter_resistor_2

  IMPLICIT NONE
  REAL::r_b,r_c,r_e,a_v,beta

  PRINT*,'Please enter the value for base resistor, collector resistor, votlage gain and current gain'
  PRINT*,'  ' !print out a space
  PRINT*,'Base Resistor:'
  READ*,r_b
  PRINT*,'Collector Resistor:'
  READ*,r_c
  PRINT*,'Voltage Gain:'
  READ*,a_v
  PRINT*,'Current Gain (beta):'
  READ*,beta
  PRINT*,'  ' !print out a space

          r_e=((beta*r_c)-(a_v*r_b))/(a_v*(1+beta))
          !calculate a specific value of emitter resistor with a specific given votlage and current gain.

          IF (r_e<0.) THEN
            !print out only the positive value of emitter resistor
            PRINT*,'ERROR: The emitter resistor has to be bigger to equal to zero!'
            PRINT*,'PLEASE ENTER A NEW SET OF VALUE!!'
          ELSE
            PRINT*,'Results:'
            PRINT*,'Voltage Gain:',a_v
            PRINT*,'Current Gain (beta):',beta
            PRINT*,'Emitter Resistor:',r_e
          END IF

END SUBROUTINE emitter_resistor_2

!jc  Fairly good program.  Though none of the calculations are particularly
!jc  difficult, this program does quite a few things.
