2010-09-18 16:56:48 +00:00
|
|
|
/*
|
|
|
|
Copyright (c) 2010 Brian Silverman, Barry Silverman
|
|
|
|
|
|
|
|
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
|
|
of this software and associated documentation files (the "Software"), to deal
|
|
|
|
in the Software without restriction, including without limitation the rights
|
|
|
|
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
|
|
copies of the Software, and to permit persons to whom the Software is
|
|
|
|
furnished to do so, subject to the following conditions:
|
|
|
|
|
|
|
|
The above copyright notice and this permission notice shall be included in
|
|
|
|
all copies or substantial portions of the Software.
|
|
|
|
|
|
|
|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
|
|
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
|
|
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
|
|
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
|
|
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
|
|
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
|
|
|
THE SOFTWARE.
|
|
|
|
*/
|
|
|
|
|
|
|
|
var ctrace = false;
|
2010-09-28 19:22:50 +00:00
|
|
|
var traceTheseNodes = [];
|
|
|
|
var traceTheseTransistors = [];
|
2010-09-25 10:29:26 +00:00
|
|
|
var loglevel = 0;
|
2010-10-15 00:16:43 +00:00
|
|
|
var recalclist = new Array();
|
|
|
|
var recalcHash = new Array();
|
|
|
|
var group = new Array();
|
2010-09-18 16:56:48 +00:00
|
|
|
|
|
|
|
function recalcNodeList(list){
|
|
|
|
var n = list[0];
|
2010-10-15 00:16:43 +00:00
|
|
|
recalclist = new Array();
|
|
|
|
recalcHash = new Array();
|
2010-09-18 16:56:48 +00:00
|
|
|
for(var j=0;j<100;j++){ // loop limiter
|
|
|
|
if(list.length==0) return;
|
2010-09-28 19:22:50 +00:00
|
|
|
if(ctrace) {
|
|
|
|
var i;
|
|
|
|
for(i=0;i<traceTheseNodes.length;i++) {
|
|
|
|
if(list.indexOf(traceTheseNodes[i])!=-1) break;
|
|
|
|
}
|
|
|
|
if((traceTheseNodes.length==0)||(list.indexOf(traceTheseNodes[i])==-1)) {
|
|
|
|
console.log('recalcNodeList iteration: ', j, list.length, 'nodes');
|
|
|
|
} else {
|
|
|
|
console.log('recalcNodeList iteration: ', j, list.length, 'nodes', list);
|
|
|
|
}
|
|
|
|
}
|
2010-10-15 01:15:47 +00:00
|
|
|
list.forEach(recalcNode);
|
2010-09-18 16:56:48 +00:00
|
|
|
list = recalclist;
|
|
|
|
recalclist = new Array();
|
2010-10-15 00:16:43 +00:00
|
|
|
recalcHash = new Array();
|
2010-09-18 16:56:48 +00:00
|
|
|
}
|
2010-09-19 07:02:26 +00:00
|
|
|
if(ctrace) console.log(n,'looping...');
|
2010-09-18 16:56:48 +00:00
|
|
|
}
|
|
|
|
|
2010-10-15 00:16:43 +00:00
|
|
|
function recalcNode(node){
|
2010-09-18 16:56:48 +00:00
|
|
|
if(node==ngnd) return;
|
|
|
|
if(node==npwr) return;
|
2010-10-15 12:11:43 +00:00
|
|
|
getNodeGroup(node);
|
|
|
|
var newState = getNodeValue();
|
2010-09-28 19:22:50 +00:00
|
|
|
if(ctrace && (traceTheseNodes.indexOf(node)!=-1))
|
|
|
|
console.log('recalc', node, group);
|
2010-10-15 12:11:43 +00:00
|
|
|
group.forEach(function(i){
|
|
|
|
var n = nodes[i];
|
|
|
|
if(n.state==newState) return;
|
2010-10-15 00:16:43 +00:00
|
|
|
n.state = newState;
|
2010-10-15 12:11:43 +00:00
|
|
|
n.gates.forEach(function(t){
|
|
|
|
if(n.state) turnTransistorOn(t);
|
|
|
|
else turnTransistorOff(t);});
|
|
|
|
});
|
2010-09-18 16:56:48 +00:00
|
|
|
}
|
|
|
|
|
2010-10-15 00:16:43 +00:00
|
|
|
function turnTransistorOn(t){
|
2010-09-18 16:56:48 +00:00
|
|
|
if(t.on) return;
|
2010-09-28 19:22:50 +00:00
|
|
|
if(ctrace && (traceTheseTransistors.indexOf(t.name)!=-1))
|
|
|
|
console.log(t.name, 'on', t.gate, t.c1, t.c2);
|
2010-09-18 16:56:48 +00:00
|
|
|
t.on = true;
|
2010-10-15 00:16:43 +00:00
|
|
|
addRecalcNode(t.c1);
|
2010-09-18 16:56:48 +00:00
|
|
|
}
|
|
|
|
|
2010-10-15 00:16:43 +00:00
|
|
|
function turnTransistorOff(t){
|
2010-09-18 16:56:48 +00:00
|
|
|
if(!t.on) return;
|
2010-09-28 19:22:50 +00:00
|
|
|
if(ctrace && (traceTheseTransistors.indexOf(t.name)!=-1))
|
|
|
|
console.log(t.name, 'off', t.gate, t.c1, t.c2);
|
2010-09-18 16:56:48 +00:00
|
|
|
t.on = false;
|
2010-10-15 00:16:43 +00:00
|
|
|
addRecalcNode(t.c1);
|
|
|
|
addRecalcNode(t.c2);
|
2010-09-18 16:56:48 +00:00
|
|
|
}
|
|
|
|
|
2010-10-15 00:16:43 +00:00
|
|
|
function addRecalcNode(nn){
|
2010-10-15 01:00:07 +00:00
|
|
|
if(nn==ngnd) return;
|
|
|
|
if(nn==npwr) return;
|
|
|
|
if(recalcHash[nn] == 1)return;
|
|
|
|
recalclist.push(nn);
|
|
|
|
recalcHash[nn] = 1;
|
2010-09-18 16:56:48 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
function getNodeGroup(i){
|
2010-10-15 00:16:43 +00:00
|
|
|
group = new Array();
|
|
|
|
addNodeToGroup(i);
|
2010-09-18 16:56:48 +00:00
|
|
|
}
|
|
|
|
|
2010-10-15 00:16:43 +00:00
|
|
|
function addNodeToGroup(i){
|
2010-10-14 02:00:01 +00:00
|
|
|
if(group.indexOf(i) != -1) return;
|
2010-09-18 16:56:48 +00:00
|
|
|
group.push(i);
|
|
|
|
if(i==ngnd) return;
|
|
|
|
if(i==npwr) return;
|
2010-10-15 12:11:43 +00:00
|
|
|
nodes[i].c1c2s.forEach(
|
2010-10-15 00:16:43 +00:00
|
|
|
function(t){
|
2010-10-15 12:11:43 +00:00
|
|
|
if(!t.on) return;
|
|
|
|
var other;
|
|
|
|
if(t.c1==i) other=t.c2;
|
|
|
|
if(t.c2==i) other=t.c1;
|
|
|
|
addNodeToGroup(other);});
|
2010-09-18 16:56:48 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2010-10-15 00:16:43 +00:00
|
|
|
function getNodeValue(){
|
2010-10-15 01:00:07 +00:00
|
|
|
if(arrayContains(group, ngnd)) return false;
|
|
|
|
if(arrayContains(group, npwr)) return true;
|
2010-10-15 12:11:43 +00:00
|
|
|
for(var i in group){
|
|
|
|
var nn = group[i];
|
|
|
|
var n = nodes[nn];
|
|
|
|
if(n.pullup) return true;
|
|
|
|
if(n.pulldown) return false;
|
|
|
|
if(n.state) return true;
|
|
|
|
}
|
2010-10-15 01:00:07 +00:00
|
|
|
return false;
|
2010-09-18 16:56:48 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
function isNodeHigh(nn){
|
2010-10-13 21:53:40 +00:00
|
|
|
return(nodes[nn].state);
|
2010-09-18 16:56:48 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
function saveString(name, str){
|
|
|
|
var request = new XMLHttpRequest();
|
|
|
|
request.onreadystatechange=function(){};
|
|
|
|
request.open('PUT', 'save.php?name='+name, true);
|
|
|
|
request.setRequestHeader('Content-Type', 'text/plain');
|
|
|
|
request.send(str);
|
|
|
|
}
|
|
|
|
|
|
|
|
function allNodes(){
|
|
|
|
var res = new Array();
|
2017-03-11 04:09:20 +00:00
|
|
|
var ii = 0;
|
|
|
|
for(var i in nodes) {
|
|
|
|
// Don't feed numeric strings to recalcNodeList(). Numeric
|
|
|
|
// strings can cause a (data dependent) duplicate node number
|
|
|
|
// hiccup when accumulating a node group's list, ie:
|
|
|
|
// group => [ "49", 483, 49 ]
|
|
|
|
ii = Number( i );
|
|
|
|
if((ii!=npwr)&&(ii!=ngnd)) res.push(ii);
|
|
|
|
}
|
2010-09-18 16:56:48 +00:00
|
|
|
return res;
|
|
|
|
}
|
|
|
|
|
|
|
|
function stateString(){
|
2010-10-15 01:00:07 +00:00
|
|
|
var codes = ['l','h'];
|
2010-09-18 16:56:48 +00:00
|
|
|
var res = '';
|
|
|
|
for(var i=0;i<1725;i++){
|
|
|
|
var n = nodes[i];
|
|
|
|
if(n==undefined) res+='x';
|
|
|
|
else if(i==ngnd) res+='g';
|
2010-10-15 01:00:07 +00:00
|
|
|
else if(i==npwr) res+='v';
|
|
|
|
else res+= codes[0+n.state];
|
2010-09-18 16:56:48 +00:00
|
|
|
}
|
|
|
|
return res;
|
|
|
|
}
|
|
|
|
|
|
|
|
function showState(str){
|
2010-10-15 01:00:07 +00:00
|
|
|
var codes = {g: false, h: true, v: true, l: false};
|
2010-09-18 16:56:48 +00:00
|
|
|
for(var i=0;i<str.length;i++){
|
|
|
|
if(str[i]=='x') continue;
|
2010-10-15 01:00:07 +00:00
|
|
|
var state = codes[str[i]];
|
|
|
|
nodes[i].state = state;
|
2010-09-18 16:56:48 +00:00
|
|
|
var gates = nodes[i].gates;
|
2010-10-15 01:00:07 +00:00
|
|
|
gates.forEach(function(t){t.on=state;});
|
2010-09-18 16:56:48 +00:00
|
|
|
}
|
|
|
|
refresh();
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
function setPd(name){
|
|
|
|
var nn = nodenames[name];
|
|
|
|
nodes[nn].pullup = false;
|
|
|
|
nodes[nn].pulldown = true;
|
|
|
|
}
|
|
|
|
|
|
|
|
function setHigh(name){
|
|
|
|
var nn = nodenames[name];
|
|
|
|
nodes[nn].pullup = true;
|
|
|
|
nodes[nn].pulldown = false;
|
|
|
|
recalcNodeList([nn]);
|
|
|
|
}
|
|
|
|
|
|
|
|
function setLow(name){
|
|
|
|
var nn = nodenames[name];
|
|
|
|
nodes[nn].pullup = false;
|
|
|
|
nodes[nn].pulldown = true;
|
|
|
|
recalcNodeList([nn]);
|
|
|
|
}
|
|
|
|
|
|
|
|
function arrayContains(arr, el){return arr.indexOf(el)!=-1;}
|