/*
 *
 * SN7470.java
 *
 */
 
package chips; 
 
public class SN7470 implements jbreadboard.v1_00.ChipModel {
	private jbreadboard.ChipAccess chip;
	
	//Chip Information
	private final String Description	="And-Gated J-K Positive-Egde Triggered Flip Flops"
										 +" With Preset And Clear";
	private final String Manufacturer	="Texas Instruments";

	//Diagram
	//NB. The SN5470W has a different pinout to the rest of the range.
	private String Diagram				="SN7470.gif";
	private String Diagram5470W			="SN5470W.gif";

	//Chip Size
	private final int NumberOfPins		=7;
	private final boolean Wide			=false;


	//Pin Types
	private final String[] pintypes		={"NC","IN","IN","IN","IN","OUT","IN",
										  "OUT","IN","IN","IN","IN","IN","IN"};
	private final String[] pintypes5470W={"IN","IN","IN","IN","IN","NC","IN",
										  "IN","IN","OUT","IN","OUT","IN","IN"};
										  


	
	//Derivatives
	private int Derivative				=1;	//7470
	private int PackageType				=0;	//N
	private final String[] Derivatives	={"SN5470",
										  "SN7470"};

	//Package Types
	//Corresponds to the Derivative above
	private final String[][] PackageTypes={{"J","W"},
										  {"N"}};
										  
	//Switching Characteristics
	private int Tplh					=50;
	private int Tphl					=50;


	/* 
	 *	Methods
	 */
	
	//Simulation
	//state variables
	boolean state=true;
	boolean previousclk=true;
	
	public void reset() {
		state=true;
		previousclk=true;
	}
		
	public void simulate() {
		boolean powered=false;
		
		//pins		
		int vcc=13;
		int gnd=6;
		
		int j1=2, j2=3, nj=4;
		int k1=9, k2=10, nk=8;
		int q=7, nq=5;
		int clr=1, pre=12;
		int clk=11;

		
		if(getChipText().equals("SN5470W")) {
			vcc=3;
			gnd=10;
			
			j1=6; j2=7;  nj=8;
			k1=0; k2=13; nk=12;
			q=11; nq=9;
			clr=4; pre=2;
			clk=1;
		}
				
		if(chip.readTTL(vcc).equals("HIGH") && chip.readTTL(gnd).equals("LOW")) powered=true;
		
		//Using !equals(low) instead of equals(high) causes inputs to float high
		if(powered) {
			
			boolean j=(!chip.readTTL(j1).equals("LOW") &&
					   !chip.readTTL(j2).equals("LOW") &&
					   chip.readTTL(nj).equals("LOW"));
					   
			boolean k=(!chip.readTTL(k1).equals("LOW") &&
					   !chip.readTTL(k2).equals("LOW") &&
					   chip.readTTL(nk).equals("LOW"));
			
			if(chip.readTTL(pre).equals("LOW") && chip.readTTL(clr).equals("LOW")) {
				//pre and clr
				chip.write(q,"LOW",Tphl);
				chip.write(nq,"LOW",Tphl);
			} else if(chip.readTTL(clk).equals("LOW")) {
				if(chip.readTTL(pre).equals("LOW")) {
					//pre
				   	state=true;
				   	chip.write(q,"HIGH",Tplh);
				   	chip.write(nq,"LOW",Tphl);
				} else if(chip.readTTL(clr).equals("LOW")) {
					//clr
				   	state=false;
				   	chip.write(q,"LOW",Tphl);
				   	chip.write(nq,"HIGH",Tplh);
				}
			} else if(!chip.readTTL(clk).equals("LOW") &&
					  previousclk==false &&
					  !chip.readTTL(pre).equals("LOW") &&
					  !chip.readTTL(clr).equals("LOW")) {
					
				//positive going clock edge found
				//and pre and clr are not set
					
					 if(!j && !k) state=state;
				else if( j && !k) state=true;
				else if(!j &&  k) state=false;
				else if( j &&  k) state=!state;  //toggle
				
				if(state) {
					chip.write(q,"HIGH",Tplh);
					chip.write(nq,"LOW",Tphl);
				} else {
					chip.write(q,"LOW",Tphl);
					chip.write(nq,"HIGH",Tplh);
				}
			} else if(chip.readTTL(q).equals(chip.readTTL(nq))) {
				//found unstable state, so come out of it
				if(state) {
					chip.write(q,"HIGH",Tplh);
					chip.write(nq,"LOW",Tphl);
				} else {
					chip.write(q,"LOW",Tphl);
					chip.write(nq,"HIGH",Tplh);
				}
			}					
			//update previous-clock store
			previousclk=(!chip.readTTL(clk).equals("LOW"));
		} else {
			//standard power off events
			for(int i=0;i<getNumberOfPins()*2;i++) {
				String type=getPinType(i);
				if(!(type.equals("IN") || type.equals("NC")))
					chip.write(i,"NC",0);
			}
		}
	}
	
	public void setAccess(jbreadboard.ChipAccess a) {
		chip=a;
	}
	
	//Chip Information
 	public String getChipText() {
 		return Derivatives[Derivative] + PackageTypes[Derivative][PackageType];
 	}
 	
 	public String getDescription() {
 		return Description;
 	}
 	
 	public String getManufacturer() {
 		return Manufacturer;
 	}
 
  	//Diagram
 	public String getDiagram() {
		if(getChipText().equals("SN5470W")) return Diagram5470W;
 		else return Diagram;
 	}
 	
 	//Chip Size
 	public int getNumberOfPins() {
 		return NumberOfPins;
 	}
 
 	public boolean isWide() {
 		return Wide;
 	}
 	
 	//Pin Types
 	public String getPinType(int i) {
 		if(getChipText().equals("SN5470W")) return pintypes5470W[i];
 		else return pintypes[i];
 	}
 	
 	//Derivatives
 	public int getDerivative() {return Derivative;}
 	public int getPackage() {return PackageType;}	
 	public String[] getDerivatives() {
 		return Derivatives;
 	}
 	public String[] getPackages() {
 		return PackageTypes[Derivative];
 	}
 	
 	//select the particular derivative
 	public void setDerivative(int t) {
 		Derivative = t;
 	}
 	//select the particular package
 	public void setPackage(int p) {
 		PackageType = p;
 	}
}
