import { Gate } from "./Gate.js";
import { IC_type, gateType } from "./Enums.js"
import { Integrated } from "./Integrated.js";
import { Node } from "./Node.js";
/**
* SR_Latch
* @classdesc SR_Latch
* @extends Integrated
* @memberof module:IntegratedCiruits
*/
export class SR_Latch extends Integrated {
/**
* Constructor
* @param {*} type SR_Latch type
*/
constructor(type) {
super(type);
this.nodeSet = new Node(this.posX + 5, this.posY + 30);
this.nodeReset = new Node(this.posX + 5, this.posY + this.height - 30);
this.nodeQ = new Node(this.posX + this.width - 5, this.posY + 30, true);
this.nodeNotQ = new Node(this.posX + this.width + 5, this.posY + this.height - 30, true);
this.nodeStartID = this.nodeSet.id;
}
/**
* Destroy this SR_Latch
*/
destroy() {
this.nodeSet.destroy();
this.nodeReset.destroy();
this.nodeQ.destroy();
this.nodeNotQ.destroy();
}
/**
* Draw this SR_Latch
*/
draw() {
super.draw();
this.generateOutput();
this.nodeSet.updatePosition(this.posX + 5, this.posY + 30);
this.nodeReset.updatePosition(this.posX + 5, this.posY + this.height - 30);
this.nodeQ.updatePosition(this.posX + this.width - 5, this.posY + 30);
this.nodeNotQ.updatePosition(this.posX + this.width - 5, this.posY + this.height - 30);
this.nodeSet.draw();
this.nodeReset.draw();
this.nodeQ.draw();
this.nodeNotQ.draw();
}
/**
* Refresh this SR_Latch node ID
*/
refreshNodes()
{
let currentID = this.nodeStartID;
this.nodeSet.setID(currentID);
currentID++;
this.nodeReset.setID(currentID);
currentID++;
this.nodeQ.setID(currentID);
currentID++;
this.nodeNotQ.setID(currentID);
}
/**
* Generate this SR_Latch output
*/
generateOutput() // virtual
{
}
/**
* Called when mouse is clicked
* @returns {Boolean} Boolean
*/
mouseClicked() {
let result = this.isMouseOver();
result |= this.nodeSet.mouseClicked();
result |= this.nodeReset.mouseClicked();
result |= this.nodeQ.mouseClicked();
result |= this.nodeNotQ.mouseClicked();
return result;
}
/**
* Convert SR_Latch type string into a number
* @param {String} str SR_Latch type
* @returns {Number} Return SR_Latch type by number
*/
static convertToType(str) {
switch (str) {
case "NAND":
return gateType.NAND;
case "NOR":
return gateType.NOR;
}
}
}
/**
* SR_Latch Asyncronus
* @classdesc SR_Latch Asyncronus
* @extends SR_Latch
* @memberof module:IntegratedCiruits
*/
export class SR_LatchAsync extends SR_Latch {
/**
* Constructor
* @param {*} gate Used to determine the SR_LatchAsync type
* @param {*} stabilize Flag for stabilize the SR_LatchAsync or not
*/
constructor(gate, stabilize) {
super(IC_type.SR_LATCH_ASYNC);
this.gateSet = null;
this.gateReset = null;
this.gateType = gate;
this.stabilize = stabilize;
switch (this.gateType) {
case gateType.NAND:
this.gateSet = new Gate("NAND");
this.gateReset = new Gate("NAND");
break;
case gateType.NOR:
this.gateSet = new Gate("NOR");
this.gateReset = new Gate("NOR");
break;
default:
alert("Gate not supported for this IC " + gateType);
break;
}
if (stabilize) {
// reset
this.gateReset.input[0].value = true;
this.gateSet.generateOutput();
this.gateReset.generateOutput();
}
}
/**
* Destroy this SR_LatchAsync
*/
destroy() {
super.destroy();
for (let i = 0; i < this.gateReset.input.length; i++) {
this.gateReset.input[i].destroy();
delete this.gateReset.input[i];
}
for (let i = 0; i < this.gateSet.input.length; i++) {
this.gateSet.input[i].destroy();
delete this.gateSet.input[i];
}
}
/**
* Generate this SR_LatchAsync output
*/
generateOutput() {
this.gateSet.input[0].value = this.nodeSet.value;
this.gateSet.input[1].value = this.gateReset.output.value;
this.gateReset.input[0].value = this.nodeReset.value;
this.gateReset.input[1].value = this.gateSet.output.value;
this.gateSet.generateOutput();
this.gateReset.generateOutput();
this.nodeQ.value = this.gateReset.output.value;
this.nodeNotQ.value = this.gateSet.output.value;
}
}
/**
* SR_Latch Syncronus
* @classdesc SR_Latch Syncronus
* @extends SR_Latch
* @memberof module:IntegratedCiruits
*/
export class SR_LatchSync extends SR_Latch {
/**
* Constructor
* @param {*} gate Used to determine the SR_LatchSync type
* @param {*} stabilize Flag for stabilize the SR_LatchSync or not
*/
constructor(gate, stabilize) {
super(IC_type.SR_LATCH_SYNC);
this.nodeClock = new Node(this.posX + this.width - 5, this.posY + (this.height / 2));
this.asyncLatch = new SR_LatchAsync(gate, stabilize);
this.gateSet = null;
this.gateReset = null;
this.gateType = gate;
this.stabilize = stabilize;
switch (this.gateType) {
case gateType.NAND:
this.gateSet = new Gate("NAND");
this.gateReset = new Gate("NAND");
break;
case gateType.NOR:
this.gateSet = new Gate("AND");
this.gateReset = new Gate("AND");
break;
default:
alert("Gate not supported for this IC");
break;
}
if (stabilize) {
// reset
this.nodeClock.setValue(true);
this.nodeReset.setValue(true);
this.generateOutput();
this.nodeClock.setValue(false);
this.nodeReset.setValue(false);
}
}
/**
* Destroy this SR_LatchSync
*/
destroy() {
super.destroy();
this.nodeClock.destroy();
this.gateSet.destroy();
this.gateReset.destroy();
this.asyncLatch.destroy();
}
/**
* Draw this SR_LatchSync
*/
draw() {
super.draw();
this.nodeClock.updatePosition(this.posX + 5, this.posY + (this.height / 2));
this.nodeClock.draw();
}
/**
* Refresh this SR_LatchSync node ID
*/
refreshNodes()
{
super.refreshNodes();
let currentID = this.nodeStartID + 4;
this.nodeClock.setID(currentID);
}
/**
* Generate this SR_LatchSyncoutput
*/
generateOutput() {
this.gateSet.input[0].value = this.nodeSet.value;
this.gateSet.input[1].value = this.nodeClock.value;
this.gateReset.input[0].value = this.nodeReset.value;
this.gateReset.input[1].value = this.nodeClock.value;
this.gateSet.generateOutput();
this.gateReset.generateOutput();
this.asyncLatch.nodeSet.value = this.gateSet.output.value;
this.asyncLatch.nodeReset.value = this.gateReset.output.value;
this.asyncLatch.generateOutput();
if (this.gateType == gateType.NOR) {
this.nodeQ.value = this.asyncLatch.nodeQ.value;
this.nodeNotQ.value = this.asyncLatch.nodeNotQ.value;
} else {
// invert if NAND
this.nodeNotQ.value = this.asyncLatch.nodeQ.value;
this.nodeQ.value = this.asyncLatch.nodeNotQ.value;
}
}
/**
* Called when mouse is clicked
* @returns {Boolean} Boolean
*/
mouseClicked() {
let result = super.mouseClicked();
result |= this.nodeClock.mouseClicked();
return result;
}
}