364 lines
12 KiB
JavaScript
364 lines
12 KiB
JavaScript
class ICInput extends Element {
|
|
setPinName(pinname) {
|
|
// Dont actually need it to do anything
|
|
this.Properties[0].CurrentValue = pinname;
|
|
this.Output = false;
|
|
this.drawElement(0,0,this.StaticCtx);
|
|
}
|
|
|
|
constructor(_Container, RestoreData = null,logicengine) {
|
|
super(_Container, RestoreData ,logicengine,0);
|
|
this.removeProperty("Inputs");
|
|
this.Task = new Task("ICInputTask","CLOCK",0,1,this.ClockTick.bind(this));
|
|
this.Name = "ICInput";
|
|
this.Input = false;
|
|
|
|
let pinNameProperty = new ElementProperty("Pin Name","string",{CBObject: this,CBFunction: "setPinName"},"Pin","Pin",false,1,32);
|
|
this.Properties.push(pinNameProperty);
|
|
this.LogicEngine.Scheduler.addTask(this.Task);
|
|
|
|
if (RestoreData) {
|
|
pinNameProperty.CurrentValue = RestoreData.Properties[0].CurrentValue;
|
|
}
|
|
}
|
|
|
|
toJSON(key) {
|
|
let superjson = super.toJSON(key);
|
|
superjson.Task = {
|
|
Enabled: this.Task.Enabled,
|
|
Time: this.Task.Time,
|
|
LastCall: Date.now() - this.Task.LastCall,
|
|
CallCount: this.Task.CallCount
|
|
};
|
|
return superjson;
|
|
}
|
|
|
|
setInput(notused = 0,value) {
|
|
|
|
if (notused > 0) return;
|
|
|
|
if (value === false) this.Input = false;
|
|
if (value !== false) this.Input = true;
|
|
this.Inputs[0] = this.Input;
|
|
this.drawElement(0,0,this.StaticCtx);
|
|
|
|
if (!this.Task.Enabled) {
|
|
this.Task.LastCall = 0;
|
|
this.Task.Enabled = true;
|
|
}
|
|
}
|
|
|
|
ClockTick() {
|
|
this.Output = this.Input;
|
|
this.Task.Enabled = false;
|
|
this.Task.LastCall = 0;
|
|
this.drawElement(0,0,this.StaticCtx);
|
|
|
|
for (let a = 0; a < this.OutputConnections.length; a++) {
|
|
this.LogicEngine.RecursionCount = 0;
|
|
this.OutputConnections[a].Element.setInput(this.OutputConnections[a].Input, this.getOutput());
|
|
}
|
|
}
|
|
|
|
Delete() {
|
|
super.Delete();
|
|
this.LogicEngine.Scheduler.deleteTask(this.Task);
|
|
}
|
|
|
|
getOutput(Output=0) {
|
|
if (super.getOutput() === 0) return false;
|
|
return this.Output;
|
|
}
|
|
|
|
drawElement(x,y,ctx) {
|
|
if (this.LogicEngine.ActiveContainer !== this._Container) return; // No point if we aren't visible
|
|
/*
|
|
Draw routine for the element
|
|
*/
|
|
this.StaticCanvas.width = this.Width;
|
|
this.StaticCanvas.height = this.Height;
|
|
|
|
let drawOverline = false;
|
|
let label = (this.Properties[0].CurrentValue) ? this.Properties[0].CurrentValue.toString() : "";
|
|
if (label.charAt(0) == "!" || label.charAt(0) == "~") {
|
|
// Draw a NOT line
|
|
drawOverline = true;
|
|
label = label.substring(1);
|
|
}
|
|
|
|
this.drawBorderBox(ctx,x+10,y,this.Width-30,this.Height);
|
|
this.drawTextCentered(ctx,x,y+2,this.Width-10,14,this.Designator,"12px Console");
|
|
this.drawTextCentered(ctx,x,y,this.Width-10,this.Height,label,"12px Console",undefined,drawOverline);
|
|
this.drawOutputs(ctx,x,y);
|
|
}
|
|
|
|
}
|
|
let ElementCatalog_ICInput = new ElementCatalog_Element("ICInput","Allows for external signal to be applied to the design when used as an IC.","-<|",ICInput,[]);
|
|
ElementReferenceTable.push(ElementCatalog_ICInput);
|
|
ElementCategory_ICs.addElement(ElementCatalog_ICInput);
|
|
|
|
class ICOutput extends Element {
|
|
setPinName(pinname) {
|
|
// Dont actually need it to do anything
|
|
this.Properties[0].CurrentValue = pinname;
|
|
this.Output = false;
|
|
this.drawElement(0,0,this.StaticCtx);
|
|
}
|
|
|
|
constructor(_Container, RestoreData = null,logicengine) {
|
|
super(_Container, RestoreData ,logicengine,1);
|
|
this.removeProperty("Inputs");
|
|
this.Task = new Task("ICOutputTask","CLOCK",0,1,this.ClockTick.bind(this));
|
|
this.Name = "ICOutput";
|
|
this.Input = false;
|
|
this.NoOutput = true;
|
|
this.ParentIC = false;
|
|
|
|
let pinNameProperty = new ElementProperty("Pin Name","string",{CBObject: this,CBFunction: "setPinName"},"Pin","Pin",false,1,32);
|
|
this.Properties.push(pinNameProperty);
|
|
this.LogicEngine.Scheduler.addTask(this.Task);
|
|
if (RestoreData) {
|
|
pinNameProperty.CurrentValue = RestoreData.Properties[0].CurrentValue;
|
|
}
|
|
|
|
}
|
|
|
|
setParent(element) {
|
|
this.ParentIC = element;
|
|
}
|
|
|
|
toJSON(key) {
|
|
let superjson = super.toJSON(key);
|
|
superjson.Task = {
|
|
Enabled: this.Task.Enabled,
|
|
Time: this.Task.Time,
|
|
LastCall: Date.now() - this.Task.LastCall,
|
|
CallCount: this.Task.CallCount
|
|
};
|
|
return superjson;
|
|
}
|
|
|
|
setInput(notused = 0,value) {
|
|
if (notused > 0) return;
|
|
value = this._Container.isHigh(this,0);
|
|
if (value === false) this.Input = false;
|
|
if (value !== false) this.Input = true;
|
|
this.Inputs[0] = this.Input;
|
|
this.drawElement(0,0,this.StaticCtx);
|
|
|
|
if (!this.Task.Enabled) {
|
|
this.Task.LastCall = 0;
|
|
this.Task.Enabled = true;
|
|
}
|
|
}
|
|
|
|
ClockTick() {
|
|
this.Output = this.Input;
|
|
this.Task.Enabled = false;
|
|
this.Task.LastCall = 0;
|
|
this.drawElement(0,0,this.StaticCtx);
|
|
|
|
for (let a = 0; a < this.OutputConnections.length; a++) {
|
|
this.LogicEngine.RecursionCount = 0;
|
|
this.OutputConnections[a].Element.setInput(this.OutputConnections[a].Input, this.getOutput());
|
|
}
|
|
|
|
if (this.ParentIC) {
|
|
this.ParentIC.drawOutputs(this.ParentIC.StaticCtx,0,0);
|
|
}
|
|
}
|
|
|
|
Delete() {
|
|
super.Delete();
|
|
this.LogicEngine.Scheduler.deleteTask(this.Task);
|
|
}
|
|
|
|
getOutput(Output=0) {
|
|
if (super.getOutput() === 0) return false;
|
|
return this.Output;
|
|
}
|
|
|
|
drawConnections(ctx, settings) {
|
|
// Don't draw connections from IC Outputs
|
|
}
|
|
|
|
drawOutputs(ctx, x, y, borderColor = "#000", circleColorFalse = "#ff0000", circleColorTrue = "#00ff00", circleColorHover = "#00ffff") {
|
|
// Don't draw outputs
|
|
}
|
|
|
|
drawElement(x,y,ctx) {
|
|
if (this.LogicEngine.ActiveContainer !== this._Container) return; // No point if we aren't visible
|
|
/*
|
|
Draw routine for the element
|
|
*/
|
|
this.StaticCanvas.width = this.Width;
|
|
this.StaticCanvas.height = this.Height;
|
|
|
|
let drawOverline = false;
|
|
let label = (this.Properties[0].CurrentValue) ? this.Properties[0].CurrentValue.toString() : "";
|
|
if (label.charAt(0) == "!" || label.charAt(0) == "~") {
|
|
// Draw a NOT line
|
|
drawOverline = true;
|
|
label = label.substring(1);
|
|
}
|
|
|
|
this.drawBorderBox(ctx,x+20,y,this.Width-10,this.Height);
|
|
this.drawTextCentered(ctx,x+20,y+2,this.Width-10,14,this.Designator,"12px Console");
|
|
this.drawTextCentered(ctx,x+20,y,this.Width-10,this.Height,label,"12px Console",undefined,drawOverline);
|
|
this.drawInputs(ctx,x,y,undefined,undefined,undefined,undefined,true);
|
|
}
|
|
}
|
|
let ElementCatalog_ICOutput = new ElementCatalog_Element("ICOutput","Allows for routing a signal externally when the design is used as an IC.","|>-",ICOutput,[]);
|
|
ElementReferenceTable.push(ElementCatalog_ICOutput);
|
|
ElementCategory_ICs.addElement(ElementCatalog_ICOutput);
|
|
|
|
class ICElement extends Element {
|
|
constructor(_Container, RestoreData = null, logicengine,ICSettings = null) {
|
|
|
|
|
|
let newContainer = false;
|
|
let icContainer = false;
|
|
try {
|
|
newContainer = loadContainer(JSON.parse(JSON.parse(ICSettings.Container)));
|
|
icContainer = loadContainer(JSON.parse(JSON.parse(ICSettings.Container)));
|
|
} catch (ex) {
|
|
newContainer = loadContainer(JSON.parse(ICSettings.Container));
|
|
icContainer = loadContainer(JSON.parse(ICSettings.Container));
|
|
}
|
|
ICSettings.Inputs = new Array();
|
|
ICSettings.Outputs = new Array();
|
|
|
|
let inputLabels = new Array();
|
|
let outputLabels = new Array();
|
|
|
|
for (let a = 0; a < newContainer.Elements.length; a++) {
|
|
if (newContainer.Elements[a] instanceof ICInput) {
|
|
let cConn = new ContainerConnection(null,newContainer,null,newContainer.Elements[a],0);
|
|
inputLabels.push(newContainer.Elements[a]?.Properties[0]?.CurrentValue);
|
|
ICSettings.Inputs.push(cConn);
|
|
}
|
|
if (newContainer.Elements[a] instanceof ICOutput) {
|
|
let cConn = new ContainerConnection(newContainer,null,newContainer.Elements[a],null,0);
|
|
outputLabels.push(newContainer.Elements[a]?.Properties[0]?.CurrentValue);
|
|
ICSettings.Outputs.push(cConn);
|
|
}
|
|
}
|
|
|
|
let totalInputs = ICSettings.Inputs.length;
|
|
let totalOutputs = ICSettings.Outputs.length;
|
|
|
|
super(_Container, RestoreData, logicengine, totalInputs);
|
|
this.removeProperty("Inputs");
|
|
this.ICBlueprint = icContainer;
|
|
this.Outputs = ICSettings.Outputs;
|
|
this.InputConnections = ICSettings.Inputs;
|
|
this.InputLabels = inputLabels;
|
|
this.OutputLabels = outputLabels;
|
|
|
|
this.Container = newContainer;
|
|
this.Name = ICSettings.Name;
|
|
this.Icon = "≡[°]≡";
|
|
this.Width = 140;
|
|
this.Height = (totalInputs >= totalOutputs) ? totalInputs*25 : totalOutputs*25;
|
|
if (this.Height < 60) this.Height = 60;
|
|
|
|
for (let a = 0; a < this.Outputs.length; a++) {
|
|
this.Outputs[a].fromElement.setParent(this);
|
|
}
|
|
|
|
let editProperty = new ElementProperty("Edit","button",{CBObject: this,CBFunction: "editIC"},"Edit IC","Edit IC",false,0,0);
|
|
this.Properties.push(editProperty);
|
|
|
|
if (RestoreData) {
|
|
//console.log(RestoreData);
|
|
}
|
|
}
|
|
|
|
toJSON(key) {
|
|
let superjson = super.toJSON(key);
|
|
superjson.IsIC = true;
|
|
let eCat = getElementInfo(this.Name);
|
|
superjson.Description = eCat.Description;
|
|
superjson.ICOutputs = this.Outputs;
|
|
superjson.InputConnections = this.InputConnections;
|
|
superjson.ICBlueprint = this.ICBlueprint;
|
|
superjson.ICContainer = this.Container;
|
|
return superjson;
|
|
}
|
|
|
|
editIC(value) {
|
|
if (this.LogicEngine.StashedContainer) {
|
|
this.LogicEngine.StashedContainer.push(this.LogicEngine.ActiveContainer);
|
|
} else {
|
|
this.LogicEngine.StashedContainer = new Array();
|
|
this.LogicEngine.StashedContainer.push(this.LogicEngine.ActiveContainer);
|
|
}
|
|
|
|
this.LogicEngine.ActiveContainer = this.ICBlueprint;
|
|
this.LogicEngine.RedrawStatics();
|
|
}
|
|
|
|
Disconnect(element = false) {
|
|
super.Disconnect(element);
|
|
if (element) {
|
|
for (let a = 0; a < this.Outputs.length; a++) {
|
|
if (this.Outputs[a].toElement == element || this.Outputs[a].fromElement == element) {
|
|
if (this.Outputs[a].toElement == element) {
|
|
// It's a too element, we need to tell it we are not high anymore
|
|
} else {
|
|
// Its a from element, we need to tell it's too element
|
|
}
|
|
}
|
|
}
|
|
} else {
|
|
// We are disconnecting all of our own connections
|
|
for (let a = 0; a < this.Outputs.length; a++) {
|
|
|
|
}
|
|
}
|
|
}
|
|
|
|
addConnection(container, element, input, output = 0) {
|
|
super.addConnection(container, element, input, output);
|
|
this.Outputs[output].toElementContainer = container;
|
|
this.Outputs[output].toElement = element;
|
|
this.Outputs[output].Input = input;
|
|
this.Outputs[output].fromElement.addConnection(container,element,input,0);
|
|
}
|
|
|
|
setInput(Input, Value) {
|
|
if (this.InputConnections.length >= Input) {
|
|
// No need to worry about recursion as this goes to an input element which is buffered
|
|
Value = this._Container.isHigh(this,Input);
|
|
this.Inputs[Input] = (Value === false) ? false : true;
|
|
this.drawElement(0,0,this.StaticCtx);
|
|
this.InputConnections[Input].toElement.setInput(0,Value);
|
|
}
|
|
return false;
|
|
}
|
|
|
|
getOutput(Output = 0) {
|
|
if (super.getOutput() === 0) return false;
|
|
if (this.Outputs.length >= Output) {
|
|
return this?.Outputs[Output]?.fromElement?.getOutput(this?.Outputs[Output]?.Input);
|
|
}
|
|
return false;
|
|
}
|
|
|
|
drawElement(x,y,ctx) {
|
|
if (this.LogicEngine.ActiveContainer !== this._Container) return; // No point if we aren't visible
|
|
/*
|
|
Draw routine for the element
|
|
*/
|
|
this.StaticCanvas.width = this.Width;
|
|
this.StaticCanvas.height = this.Height;
|
|
|
|
this.clearStatic();
|
|
this.drawBorderBox(ctx,x+20,y,this.Width-40,this.Height);
|
|
this.drawTextCentered(ctx,x,y,this.Width,this.Height,this.Icon,"12px Console");
|
|
this.drawTextCentered(ctx,x,(y+this.Height)-14,this.Width,14,this.Designator,"10px Console","#000");
|
|
this.drawInputs(ctx,x,y,undefined,undefined,undefined,undefined,true);
|
|
this.drawOutputs(ctx,x,y,undefined,undefined,undefined,undefined,true);
|
|
}
|
|
}
|