// Calculate energy band diagram of a npn transistor.
// (Java 1.1 or later version)
import java.awt.*;
import java.awt.event.*;
import java.applet.*;
import java.lang.String.*;
import java.lang.Double.*;
import java.lang.Math.*;

public class NPNTransistor extends Applet implements ActionListener
{

   TextField neField, nbField, nColField, niField, ncField, nvField, tField, vBEField, vBCField;
   String message = ""; // String containing system messages

   double ne;		// Density of donor impurity atoms, n-type(cm^-3) emit
   double nb;           // Density of acceptor impurity atoms, p-type(cm^-3) b
   double nCol;		// Density of donor impurity atoms, n-type(cm^-3) coll
   double ni;		// Intrinsic concentration of electrons(cm^-3)
   double temperature;	// Temperature(K) 
   double vBE;		// Base-emitter potential(V)
   double vBC;		// Base-collecter potential(V)


   double k = 1.38E-23;		// Boltzmann's Constant(J/K)
   double kev = 8.62E-5;	// Boltzmann's Constant(eV/K)
   double hbar = 1.054E-34;	// Planck's Constant(J*sec)
   double h = 6.625E-34;	// Plank's Constant(J*sec)
   double pi = 3.14159;		// pI
   double m0 = 9.11E-31;	// Electron mass(kg)
   double e = 1.6E-19;		// Charge on an electron(Coulombs)
   double epsilon0 = 8.85E-14;	// Permittivity of Free Space(F/cm)
   double nc = 2.8E19;		// Density of states - conduction band(cm^-3)
   double nv = 1.04E19;		// Density of states - valence band(cm^-3)

   double phiFE;		// Potential diff. between Efi and Ef, n-type E
   double phiFB;                // Potential diff. between Efi and Ef, p-type B
   double phiFC;                // Potential diff. between Efi and Ef, n-type C
   double vbi;			// Built in voltage level.
   double phiCFE;               // Ec - EF potential n-type, emitter region
   double phiCFB;		// Ec - EF potential p-type, base region
   double phiCFC;               // Ec - EF potential n-type, collector region
   double phiFVE;               // Ef - Ev potential n-type, emitter region
   double phiFVB;		// Ef - Ev potential p-type, base region
   double phiFVC;               // Ef - Ev potential n-type, collector region

   Color blue = new Color( 0, 0, 255 );
   Color red = new Color( 255, 0, 0 );
   Color green = new Color( 0, 255, 0 );
   Color black = new Color( 0, 0, 0 );
   Color dkGray = new Color( 64, 64, 64 );
   Color gray = new Color( 128, 128, 128 );
   Color ltGray = new Color( 172, 172, 172 );
   Color white = new Color( 255, 255, 255 );

   int scale = 25;		// Volts/pixel
   int fEOffset;		// Offset due to emitter Fermi level
   int fCOffset;		// Offset due to collector Fermi level
   int phiFEOffset;		// Offset due to emiiter Quasi-Fermi level
   int phiFBOffset;		// Offset due to base Quasi-Fermi level
   int phiFCOffset;		// Offset due to collector Quasi-Fermi level
   int phiCFEOffset;		// Offset to emitter region C.B.
   int phiCFBOffset;		// Offset to base region C.B.
   int phiCFCOffset;		// Offset to collector region C.B.
   int phiFVEOffset;            // Offset to emitter region V.B.
   int phiFVBOffset;            // Offset to base region V.B.
   int phiFVCOffset;            // Offset to collector region V.B.




   public void init()
   {
	Label neLabel = new Label( "Density of donor atoms n-type emitter(cm^-3): ", Label.RIGHT );
	Label nbLabel = new Label( "Density of acceptor atoms p-type base(cm^-3): ", Label.RIGHT );
	Label nColLabel = new Label( "Density of donor atoms n-type collector(cm^-3): ", Label.RIGHT );
	Label niLabel = new Label( "Intinsic concentration of electrons(cm^-3): ", Label.RIGHT );
	Label ncLabel = new Label( "Effective density of states in the conduction band(cm^-3): ", Label.RIGHT );
	Label nvLabel = new Label( "Effective density of states in the valence band(cm^-3): ", Label.RIGHT );
	Label tLabel = new Label( "Temperature(K): ", Label.RIGHT );
	Label vBELabel = new Label( "Base-emitter potential(mV): ", Label.RIGHT );
	Label vBCLabel = new Label( "Base-collector potential(mV): ", Label.RIGHT );

	neField = new TextField( 20 );
	nbField = new TextField( 20 );
	nColField = new TextField( 20 );
	niField = new TextField( 12 );
	ncField = new TextField( 20 );
	nvField = new TextField( 20 );
	tField = new TextField( 4 );
	vBEField = new TextField( 6 );
	vBCField = new TextField( 6 );


	// Add controls
	add( neLabel );
	add( neField );
	add( nbLabel );
	add( nbField );
	add( nColLabel );
	add( nColField );
	add( niLabel );
	add( niField );
	add( ncLabel );
	add( ncField );
	add( nvLabel );
	add( nvField );
	add( tLabel );
	add( tField );
	add( vBELabel );
	add( vBEField );
	add( vBCLabel );
	add( vBCField );



	// Register ActionListeners to receive action events.
	neField.addActionListener( this );
	nbField.addActionListener( this );
	nColField.addActionListener( this );
	niField.addActionListener( this );
	ncField.addActionListener( this );
	nvField.addActionListener( this );
	tField.addActionListener( this );
	vBEField.addActionListener( this );
	vBCField.addActionListener( this );

   }

   // ActionListeners.
   public void actionPerformed( ActionEvent ae )
   {
	repaint();
   }

   public void paint( Graphics g )
   {

	message = "";

	try
	{
		ne = 1 * (double)Long.parseLong( neField.getText() );
	}
	catch( NumberFormatException exceptionText )
	{
		message = "\"Ne\" field must contain a number: " + exceptionText;
		ne = 1.0;
	}
	try
	{
		nb = 1 * (double)Long.parseLong( nbField.getText() );
	}
	catch( NumberFormatException exceptionText )
	{
		message = "\"Nb\" field must contain a number: " + exceptionText;
		nb = 1.0;
	}
	try
	{
		nCol = 1 * (double)Long.parseLong( nColField.getText() );
	}
	catch( NumberFormatException exceptionText )
	{
		message = "\"Ncol\" field must contain a number: " + exceptionText;
		nCol = 1.0;
	}
	try
	{
		ni = 1 * (double)Long.parseLong( niField.getText() );
	}
	catch( NumberFormatException exceptionText )
	{
		message = "\"ni\" field must contain a number: " + exceptionText;
		ni = 1.5E10;	// Silicon intrinsic concentration of e-
	}
	try
	{
		nc = 1 * (double)Long.parseLong( ncField.getText() );
	}
	catch( NumberFormatException exceptionText )
	{
		message = "\"Nc\" field must contain a number: " + exceptionText;
		nc = 2.8E19;	// Silicon effective density of states CB
	}
	try
	{
		nv = 1 * (double)Long.parseLong( nvField.getText() );
	}
	catch( NumberFormatException exceptionText )
	{
		message = "\"Nv\" field must contain a number: " + exceptionText;
		nv = 1.04E19;	// Silicon effective density of states VB
	}
	try
	{
		temperature = 1 * (double)Long.parseLong( tField.getText() );	
	}
	catch( NumberFormatException exceptionText )
	{
		message = "\"T\" field must contain a number: " + exceptionText;
		temperature = 300.0;
	}
	try
	{
		vBE = 1E-3 * (double)Long.parseLong( vBEField.getText() );	
	}
	catch( NumberFormatException exceptionText )
	{
		message = "\"Vbe\" field must contain a number: " + exceptionText;
		vBE = 0.0;
	}
	try
	{
		vBC = 1E-3 * (double)Long.parseLong( vBCField.getText() );	
	}
	catch( NumberFormatException exceptionText )
	{
		message = "\"Vbc\" field must contain a number: " + exceptionText;
		vBC = 0.0;
	}

	
	
	
	// Calculate Vbi, built in voltage
	phiFE = -(k*temperature/e)*Math.log((ne)/(ni * ni));
	phiFB = (k*temperature/e)*Math.log((nb)/(ni * ni));
	phiFC = -(k*temperature/e)*Math.log((nCol)/(ni * ni));
	vbi = Math.abs(phiFE) + Math.abs(phiFB) - vBE;

	phiCFE = (k*temperature/e)*Math.log(nc/ne);
	phiCFB = (k*temperature/e)*Math.log(nc/((ni * ni)/nb));
	phiCFC = (k*temperature/e)*Math.log(nc/nCol);
	phiFVE = (k*temperature/e)*Math.log(nv/((ni * ni)/ne));
	phiFVB = (k*temperature/e)*Math.log(nv/nb);
	phiFVC = (k*temperature/e)*Math.log(nv/((ni * ni)/nCol));


	// Write out Input values
	g.drawString( "Nb(cm^-3): " + nb, 6 ,200 );
	g.drawString( "Ne(cm^-3): " + ne, 6, 220 );
	g.drawString( "Nc(cm^-3): " + nCol, 6, 240 );
	g.drawString( "ni(cm^-3): " + ni, 6, 260 );
	g.drawString( "T(K): " + temperature, 6, 280 );
	g.drawString( "Vbe(V): " + vBE, 6, 300 );
	g.drawString( "Vbc(V): " + vBC, 6, 320 );
	// Write out calculated values
	g.drawString( "phiCFnE(V): " + phiCFE, 6, 350 );
	g.drawString( "phiFnE(V): " + phiFE, 6, 370 );
	g.drawString( "phiFVnE(V): " + phiFVE, 6, 390 );

	g.drawString( "phiCFpB(V): " + phiCFB, 6, 420 );
	g.drawString( "phiFpB(V): " + phiFB, 6, 440 );
	g.drawString( "phiFVpB(V): " + phiFVB, 6, 460  );

	g.drawString( "phiCFnC(V): " + phiCFC, 6, 490 );
	g.drawString( "phiFnC(V): " + phiFC, 6, 510 );
	g.drawString( "phiFVnC(V): " + phiFVC, 6, 530 );

	g.drawString( "Vbi(V): " + vbi, 6, 570 );

	// Draw Fermi energy
	g.setColor(blue);
	fEOffset = (int)(vBE * scale);
	fCOffset = (int)(vBC * scale);
	g.drawLine(300, (350 + fEOffset), 410, (350 + fEOffset));
	g.drawLine(390, 350, 510, 350 );
	g.drawLine(490, (350 + fCOffset), 600, (350 + fCOffset));
	// Draw Quasi-Fermi energy.
	g.setColor(ltGray);
	phiFEOffset = (int)(phiFE * scale);
	phiFBOffset = (int)(phiFB * scale);
	phiFCOffset = (int)(phiFC * scale);

	g.drawLine(300, (350 + fEOffset + phiFEOffset), 390, (350 + fEOffset + phiFEOffset));
	g.drawLine(410, (350  + phiFBOffset), 490, (350 + phiFBOffset));
	g.drawLine(510, (350 + fCOffset + phiFCOffset), 600, (350 + fCOffset + phiFCOffset));

	// Draw conncetion of Quasi-Fermi energy levels
	g.drawLine(390, (350 + fEOffset + phiFEOffset), 410, (350  + phiFBOffset));
	g.drawLine(490, (350  + phiFBOffset), 510, (350 + fCOffset + phiFCOffset));

	// Draw Conduction band
	g.setColor(red);
	phiCFEOffset = (int)(phiCFE * scale);
	phiCFBOffset = (int)(phiCFB * scale);
	phiCFCOffset = (int)(phiCFC * scale);
	g.drawLine(300, (350 - phiCFEOffset + fEOffset - phiFEOffset), 390, (350 - phiCFEOffset + fEOffset - phiFEOffset));
	g.drawLine(410, (350 - phiCFBOffset - phiFBOffset), 490, (350 - phiCFBOffset - phiFBOffset));
	g.drawLine(510, (350 - phiCFCOffset + fCOffset - phiFCOffset), 600, (350 - phiCFCOffset + fCOffset - phiFCOffset));
	// Draw connection of conduction band
	g.drawLine(390, (350 - phiCFEOffset + fEOffset - phiFEOffset), 410, (350 - phiCFBOffset - phiFBOffset));
	g.drawLine(490, (350 - phiCFBOffset - phiFBOffset), 510, (350 - phiCFCOffset + fCOffset - phiFCOffset));

	// Draw Valence band
	g.setColor(green);
	phiFVEOffset = (int)(phiFVE * scale);
	phiFVBOffset = (int)(phiFVB * scale);
	phiFVCOffset = (int)(phiFVC * scale);
	g.drawLine(300, (350 + phiFVEOffset + fEOffset - phiFEOffset), 390, (350 + phiFVEOffset + fEOffset - phiFEOffset));
	g.drawLine(410, (350 + phiFVBOffset - phiFBOffset), 490, (350 + phiFVBOffset - phiFBOffset));
	g.drawLine(510, (350 + phiFVCOffset + fCOffset - phiFCOffset), 600, (350 + phiFVCOffset + fCOffset - phiFCOffset));
	// Draw connection of conduction band
	g.drawLine(390, (350 + phiFVEOffset + fEOffset - phiFEOffset), 410, (350 + phiFVBOffset - phiFBOffset));
	g.drawLine(490, (350 + phiFVBOffset - phiFBOffset), 510, (350 + phiFVCOffset + fCOffset - phiFCOffset));
	g.setColor(black);

	// Write out any messages
	g.drawString( "Message: " + message, 6, 600 );

   }

   // main() is the entry point when called as an application.
   // main() is not used when run as an applet.
   public static void main ( String args[] )
   {
	Frame mainWindow = new Frame ( "NPNTransistor" );
	NPNTransistor application = new NPNTransistor ();

	mainWindow.setSize ( 700, 600 );
	mainWindow.add ( "Center", application );
	mainWindow.show ();
	application.init();
   }

}
