// Gate image overlays

sor000 = new Image(60,60);	sor000.src = "images/dff000.gif"
sor001 = new Image(60,60);	sor001.src = "images/dff001.gif"
sor010 = new Image(60,60);	sor010.src = "images/dff010.gif"
sor011 = new Image(60,60);	sor011.src = "images/dff011.gif"
sor100 = new Image(60,60);	sor100.src = "images/dff100.gif"
sor101 = new Image(60,60);	sor101.src = "images/dff101.gif"
sor110 = new Image(60,60);	sor110.src = "images/dff110.gif"
sor111 = new Image(60,60);	sor111.src = "images/dff111.gif"

sor0p0 = new Image(70,75);	sor0p0.src = "images/psmx0010.gif"
sor0p1 = new Image(70,75);	sor0p1.src = "images/psmx0011.gif"
sor0s0 = new Image(70,75);	sor0s0.src = "images/psmx0100.gif"
sor0s1 = new Image(70,75);	sor0s1.src = "images/psmx0101.gif"
sor1p0 = new Image(70,75);	sor1p0.src = "images/psmx1010.gif"
sor1p1 = new Image(70,75);	sor1p1.src = "images/psmx1011.gif"
sor1s0 = new Image(70,75);	sor1s0.src = "images/psmx1100.gif"
sor1s1 = new Image(70,75);	sor1s1.src = "images/psmx1101.gif"

ups0 = new Image(60,60);	ups0.src = "images/ups0.gif"
dns0 = new Image(60,60);	dns0.src = "images/dns0.gif"
upp1 = new Image(60,60);	upp1.src = "images/upp1.gif"
dnp1 = new Image(60,60);	dnp1.src = "images/dnp1.gif"

dnv0 = new Image(60,60);	dnv0.src = "images/dnv0.gif"
dnv1 = new Image(60,60);	dnv1.src = "images/dnv1.gif"
upv0 = new Image(60,60);	upv0.src = "images/upv0.gif"
upv1 = new Image(60,60);	upv1.src = "images/upv1.gif"

line0 = new Image(2, 2);	line0.src = "/images/blue.gif"
line1 = new Image(2, 2);	line1.src = "/images/red.gif"

clkexts0 = new Image(60, 105);	clkexts0.src = "images/clkexts0.gif"
clkexts1 = new Image(60, 105);	clkexts1.src = "images/clkexts1.gif"
clkextp0 = new Image(60, 105);	clkextp0.src = "images/clkextp0.gif"
clkextp1 = new Image(60, 105);	clkextp1.src = "images/clkextp1.gif"

clkend0 = new Image(60, 105);	clkend0.src = "images/clkend0.gif"
clkend1 = new Image(60, 105);	clkend1.src = "images/clkend1.gif"

modexts0 = new Image(70, 60);	modexts0.src = "images/modexts0.gif"
modexts1 = new Image(70, 60);	modexts1.src = "images/modexts1.gif"
modextp0 = new Image(70, 60);	modextp0.src = "images/modextp0.gif"
modextp1 = new Image(70, 60);	modextp1.src = "images/modextp1.gif"

modends0 = new Image(70, 60);	modends0.src = "images/modends0.gif"
modends1 = new Image(70, 60);	modends1.src = "images/modends1.gif"
modendp0 = new Image(70, 60);	modendp0.src = "images/modendp0.gif"
modendp1 = new Image(70, 60);	modendp1.src = "images/modendp1.gif"

modctli0 = new Image(60, 45);	modctli0.src = "images/notvl-0.gif"
modctli1 = new Image(60, 45);	modctli1.src = "images/notvl-1.gif"

modctlo0 = new Image(60, 30);	modctlo0.src = "images/notv-0.gif"
modctlo1 = new Image(60, 30);	modctlo1.src = "images/notv-1.gif"



// gate input and output values

var gatesIn = new Array(0);
gatesIn[0] = new Array(6);	// 4-bit shift register p to s
gatesIn[0][0] = "0";		// serial data in
gatesIn[0][1] = "0";		// mode. 0 -> "s", 1 -> "p"
gatesIn[0][2] = "0";		// clock pulse.
gatesIn[0][3] = "0";		// parallel data in, MSB
gatesIn[0][4] = "0";
gatesIn[0][5] = "0";
gatesIn[0][6] = "0";		// parallel data in, LSB

var gatesOut = new Array(0);
gatesOut[0] = new Array(3);	// 4-bit shift register p to s
gatesOut[0][0] = "0";		// parallel out MSB
gatesOut[0][1] = "0";
gatesOut[0][2] = "0";
gatesOut[0][3] = "0";		// parallel out LSB


// gate names

var gateNames = new Array(0);
gateNames[0] = "sor";

// Input and output counts

var gateInputs = new Array(0);
gateInputs[0] = 7;

var gateOutputs = new Array(0);
gateOutputs[0] = 4;


// Pulse state information -- initialize

var pulseRestingState = new Array(0);
pulseRestingState[0] = 0;
  
var pulseState = new Array(0);
pulseState[0] = pulseRestingState[0];

var mode = "s";			// Start in serial mode


// function to handle serial/parallel mode button

function modeClick(gateID, inputID) {
	var myGate = parseInt(gateID);
	var myInput = parseInt(inputID);
	var myImage = gateNames[myGate] + myInput;
	overlay(myImage, "dn" + mode + gatesIn[myGate][myInput]);
}


// replace 'up' button if mouse is moved out of range before release

function unModeClick(gateID, inputID) {
	var myGate = parseInt(gateID);
	var myInput = parseInt(inputID);
	var myImage = gateNames[myGate] + myInput;
	overlay(myImage, "up" + mode + gatesIn[myGate][myInput]);
}


// function to handle vertical buttons

function vClick(gateID, inputID) {
	var myGate = parseInt(gateID);
	var myInput = parseInt(inputID);
	var myImage = gateNames[myGate] + myInput;
	overlay(myImage, "dnv" + gatesIn[myGate][myInput]);
}


// replace 'up' button if mouse is moved out of range before release

function unVClick(gateID, inputID) {
	var myGate = parseInt(gateID);
	var myInput = parseInt(inputID);
	var myImage = gateNames[myGate] + myInput;
	overlay(myImage, "upv" + gatesIn[myGate][myInput]);
}


// Replace the general update function with one specific to this page.

function update(gateID, inputID) {
	var myGate = parseInt(gateID);
	var myInput = parseInt(inputID);
	var myInImage = gateNames[myGate] + myInput;
	var oldInput = gatesIn[myGate][myInput];
	var newInput = (oldInput == "1") ? "0" : "1";
	gatesIn[myGate][myInput] = newInput;
	mode = (gatesIn[myGate][1] == 0) ? "s" : "p";
	// Determine output state for current inputs
	if (gatesIn[myGate][myInput] == "0" && myInput == 2) {
		for (i = 3; i > 0; i -= 1) {
			gatesOut[myGate][i]=(mode =="s")?gatesOut[myGate][i-1]:gatesIn[myGate][i+3];
		}
		gatesOut[myGate][0]=(mode =="s")?gatesIn[myGate][0]:gatesIn[myGate][3];
	}
	for (i = 3; i >= 0; i -= 1) {
		newFFImage = gateNames[myGate];
		if (i > 0) {
			newFFIn = (mode =="s") ? gatesOut[myGate][i-1] : gatesIn[myGate][i+3];
		} else {
			newFFIn = (mode =="s") ? gatesIn[myGate][0] : gatesIn[myGate][3];
		}
		newFFImage += newFFIn ;
		newFFImage += pulseState[myGate];
		newFFImage += gatesOut[myGate][i];
		newFFGate = gateNames[myGate] + i + "Gate";
		overlay(newFFGate, newFFImage);

		newMuxImage = gateNames[myGate];
		if (i > 0) {
			newMuxImage += gatesOut[myGate][i-1];
		} else {
			newMuxImage += gatesIn[myGate][0];
		}
		newMuxImage += mode;
		newMuxImage += gatesIn[myGate][i+3];
		newMuxGate = "" + gateNames[myGate] + i + "mux";
		overlay(newMuxGate, newMuxImage);

		newPMode = gatesIn[myGate][1];
		newSMode = 1 - newPMode;
		overlay("msexts" + i, "line" + newSMode);
		overlay("msextp" + i, "line" + newPMode);

		newModeImage = (i == 3) ? "modend" : "modext";
		newModeImage += mode;
		newModeImage += gatesIn[myGate][2];
		newModeGate = "modext" + i;
		overlay(newModeGate, newModeImage);

		newClkImage = (i == 3) ? "clkend" : "clkext" + mode;
		newClkImage += gatesIn[myGate][2];
		newClkGate = "clkext" + i;
		overlay(newClkGate, newClkImage);
	}
	if (myInput == 0) {
		overlay("sor0", "up" + newInput);
		overlay("sinext", "line" + newInput);
	}
	if (myInput == 1) {
		overlay("sor1", "up" + mode + newInput);
		overlay("modctl0", "modctli" + newInput);
		overlay("modctl1", "modctlo" + oldInput);
	}
	if (myInput == 2) {
		overlay("clockline", "line" + newInput);
	}
	if (myInput > 2) {
		overlay("sor" + myInput, "upv" + newInput);
	}
}
