PageRenderTime 54ms CodeModel.GetById 2ms app.highlight 45ms RepoModel.GetById 1ms app.codeStats 0ms

/webtronics/script/connections.js

http://webtronics.googlecode.com/
JavaScript | 581 lines | 499 code | 58 blank | 24 comment | 126 complexity | 4caaa8caa4e9d1aa5b95c63674343bc0 MD5 | raw file
  1Schematic.prototype.getconnects=function(elem){
  2    var pins=[];    
  3    var nodes=this.getwtxtagname(elem,"node");
  4    var matrix=this.parseMatrix(elem);
  5    var pin=this.svgRoot.createSVGPoint();
  6    for(var i=0;i<nodes.length;i++){
  7        pin.x=this.getwtxattribute(nodes[i],"x");
  8        pin.y=this.getwtxattribute(nodes[i],"y");
  9        pin = pin.matrixTransform(matrix);
 10        pins[i]={x:Math.round(pin.x),y:Math.round(pin.y)};
 11    }
 12    return pins;
 13}
 14
 15Schematic.prototype.matrixxform=function(point,matrix){
 16    var pin=this.svgRoot.createSVGPoint();
 17    pin.x=point.x;
 18    pin.y=point.y;
 19    pin=pin.matrixTransform(matrix);
 20    return {x:Math.round(pin.x),y:Math.round(pin.y)};
 21}
 22
 23/*tests if 2 point are within 3 pixels of each other*/
 24Schematic.prototype.ispoint=function(point1,point2){
 25	return (Math.abs(point2.x-point1.x)<3)&&(Math.abs(point2.y-point1.y)<3); 
 26}
 27
 28Schematic.prototype.sortnetlist=function(list){
 29	var G=[];
 30	var A=[];
 31	var B=[];
 32 	var C=[];
 33	var D=[];
 34	var I=[];
 35	var J=[];
 36	var K=[];
 37	var L=[];
 38	var M=[];
 39	var N=[];
 40	var P=[];
 41	var Q=[];
 42	var R=[];
 43	var U=[];
 44	var V=[];
 45	var wire=[];
 46	var other=[]
 47	for(var i=0;i<list.length;i++){
 48		if(list[i].type=='gnd'){
 49			G.push(list[i]);
 50		}
 51		else if(list[i].type=='v'){
 52			V.push(list[i]);
 53		}
 54		else if(list[i].type=='wire'){
 55			wire.push(list[i]);			
 56		}		
 57		else if(list[i].type=='b'){
 58			B.push(list[i]);
 59		}
 60		else if(list[i].type=='c'){
 61			C.push(list[i]);	
 62		}
 63		else if(list[i].type=='d'){
 64			D.push(list[i]);
 65		}
 66		else if(list[i].type=='i'){	
 67			J.push(list[i]);
 68		}
 69		else if(list[i].type=='j'){	
 70			J.push(list[i]);
 71		}
 72		else if(list[i].type=='k'){
 73			K.push(list[i]);
 74		}
 75		else if(list[i].type=='l'){
 76			L.push(list[i]);
 77		}
 78		else if(list[i].type=='m'){
 79			M.push(list[i]);
 80		}
 81		else if(list[i].type=='n'){
 82			N.push(list[i]);
 83		}
 84		else if(list[i].type=='plot'){
 85			P.push(list[i]);
 86		}
 87		else if(list[i].type=='q'){
 88			Q.push(list[i]);
 89		}
 90		else if(list[i].type=='r'){
 91			R.push(list[i]);
 92		}
 93		else if(list[i].type=='u'){	
 94			U.push(list[i]);
 95		}
 96/* this is the best way I could think to tell if a part i digital */
 97		else if(list[i].category=="digital"){	
 98			A.push(list[i]);
 99		}
100		else {
101            list[i].error='unknown device';
102			other.push(list[i]);
103		}
104	}
105
106	var sortfunction=function(a,b){
107        var apart=a.id.replace(a.type,"");
108        var bpart=b.id.replace(b.type,"");
109        if(!apart)apart=0;
110        if(!bpart)bpart=0;
111        return (apart>bpart);
112	};
113	V.sort(sortfunction);
114	wire.sort(sortfunction);
115	B.sort(sortfunction);
116 	C.sort(sortfunction);
117	D.sort(sortfunction);
118	I.sort(sortfunction);
119	J.sort(sortfunction);
120	K.sort(sortfunction);
121	L.sort(sortfunction);
122	M.sort(sortfunction);
123	N.sort(sortfunction);
124	P.sort(sortfunction);
125	Q.sort(sortfunction);
126	R.sort(sortfunction);
127	U.sort(sortfunction);
128	A.sort(sortfunction);
129
130	var newlist=[];
131	G.each(function(item){newlist.push(item)});		
132	G.reverse();
133	V.each(function(item){newlist.push(item)});		
134	wire.each(function(item){newlist.push(item)});		
135	B.each(function(item){newlist.push(item)});		
136	C.each(function(item){newlist.push(item)});		
137	D.each(function(item){newlist.push(item)});		
138	I.each(function(item){newlist.push(item)});		
139	J.each(function(item){newlist.push(item)});		
140	K.each(function(item){newlist.push(item)});		
141	L.each(function(item){newlist.push(item)});		
142	M.each(function(item){newlist.push(item)});		
143	N.each(function(item){newlist.push(item)});		
144	Q.each(function(item){newlist.push(item)});		
145	R.each(function(item){newlist.push(item)});		
146	U.each(function(item){newlist.push(item)});		
147	A.each(function(item){newlist.push(item)});		
148	other.each(function(item){newlist.push(item)});		
149
150/*plots go last*/
151	P.each(function(item){newlist.push(item)});		
152	return newlist;
153}
154
155/* draws wires to namewire ports with the same id*/
156Schematic.prototype.connectwires=function(list){
157    for(var i=0;i<list.length;i++){
158        if(list[i].type=="wire"){
159            for(var j=i;j<list.length;j++){
160                if((list[i]!=list[j])&&(list[i].id==list[j].id)){
161                    var node1=this.getwtxtagname(list[i].elem,"node")[0];
162                    var node2=this.getwtxtagname(list[j].elem,"node")[0];
163                    var point1={x:this.getwtxattribute(node1,"x"),y:this.getwtxattribute(node1,"y")}
164                    point1=this.matrixxform(point1,this.parseMatrix(list[i].elem));
165                    var point2={x:this.getwtxattribute(node2,"x"),y:this.getwtxattribute(node2,"y")}
166                    point2=this.matrixxform(point2,this.parseMatrix(list[j].elem));
167                    
168    				var line= this.createline('yellow',1,point1.x,point1.y,point2.x,point2.y);
169    				line.setAttributeNS(null,'class','namewire');
170    				this.info.appendChild(line);
171//console.log(line);            
172                    break; 
173               }
174            }    
175        }
176    }
177}
178
179/* test if wires are connected anywhere*/
180Schematic.prototype.getconnected=function(wirelist,wire){
181    for(var i=0;i<wirelist.length;i++){
182        for(var j=0;j<wirelist[i].length;j++){
183            for(var k=0;k<wire.length;k++){
184                if(this.ispoint(wirelist[i][j],wire[k])){
185                   return i;
186                }
187            }
188        }
189    }
190    return -1;
191}
192/*check for vectors and convert them*/
193Schematic.prototype.tovector=function(pin,nodenumber){
194    var v ="";   
195    if(pin.parentNode.tagName=="wtx:vector"){
196        var vector=Element.descendants(pin.parentNode);
197        if(pin==vector[0]){v+="["}
198        v+="a"+nodenumber;
199        if(pin==vector[vector.length-1]){v+="]";}
200    }
201    else{
202        v+="a"+nodenumber;
203    }
204
205    return v;
206}
207
208Schematic.prototype.getwtxdata=function(parts){
209    list=[];
210    for(var i=0;i<parts.length;i++){
211        var part={error:"", elem:{}, type:"", name:"", category:"", value:"", spice:"", model:""}
212/*
213        try{
214            part.nodes=this.getwtxpins(part[i]);        
215        }
216        catch{part.error="wtx:pins not found"}
217*/
218        part.elem=parts[i];
219        try{
220            part.id=this.readwtx(parts[i],'id');
221        }
222        catch(e){part.error="wtx:id not found";}    
223        try{
224            part.type=this.readwtx(parts[i],'type');
225        }
226        catch(e){
227            part.error="wtx:type not found";
228        }
229        try{
230            part.name=this.readwtx(parts[i],'name');
231        }
232        catch(e){part.error="wtx:name not found";}
233        try{
234            part.category=this.readwtx(parts[i],'category');
235        }
236        catch(e){part.error="wtx:category not found";}    
237        try{
238            part.value=this.readwtx(parts[i],'value');
239        }
240        catch(e){part.error="wtx:value not found";}    
241        try{
242            part.spice=this.readwtx(parts[i],'spice');
243        }
244        catch(e){part.error="wtx:spice not found";}    
245        try{        
246            part.model=this.readwtx(parts[i],'model');
247        }
248        catch(e){part.error="wtx:model not found";}    
249
250        list.push(part);
251    }
252    return list;
253
254}
255/*detect analog and digital mix*/
256Schematic.prototype.mixedsignals=function(analogwires,digitalwires){
257
258    for(var j=1;j<analogwires.length;j++){
259        var crossed=this.getconnected(digitalwires,analogwires[j]);
260        if(crossed>-1){
261              return true;  
262        }
263    }
264    return false;
265}
266
267
268
269/* creates all netlist data from parts data*/
270Schematic.prototype.getnodes=function(parts){
271    var sections={netlist:[],firstdir:[],simulation:[],lastdir:[]};    
272    var trannodes=[];
273    var digitalcount=1;
274    var analogcount=1;
275    var digitalwires=[];
276    var analogwires=[];
277    for(var i=0;i<parts.length; i++){
278        if(parts[i].type=="wire")continue;
279// check what type of simulation to use
280	if(parts[i].type=="plot"){
281	  if(sections.simulation.length==0 && parts[i].model.length){
282	    sections.simulation.push(parts[i].model);
283	  }
284	}
285	else if(parts[i].type=="v"){
286	  if(sections.simulation.length==0 && parts[i].model.length){
287	      sections.simulation.push(".op");
288	      sections.simulation.push(".print ac i("+parts[i].id+")");
289	      sections.simulation.push(parts[i].model);
290	  }
291	}
292	else{
293	  if(parts[i].model.match(/\.mod/i) && !parts[i].id.match(/^x/))parts[i].id="x"+parts[i].id;
294	  if(parts[i].model.length)sections.firstdir.push(parts[i].model);
295	  
296	}
297        var net={error:parts[i].error,partid:parts[i].id,pins:[],model:parts[i].value};
298        var nodes=this.getwtxtagname(parts[i].elem,"node");        
299//node numbering loop
300	for(var j=0;j<nodes.length;j++){
301            var point={x:this.getwtxattribute(nodes[j],"x"),y:this.getwtxattribute(nodes[j],"y")};
302            point=this.matrixxform(point,this.parseMatrix(parts[i].elem));
303            var wire=this.followwires(null,point);
304            if(nodes[j].parentNode.tagName=="wtx:analog"){
305                var found=this.getconnected(analogwires,wire);
306               if(parts[i].type=='gnd'){
307                    if(!analogwires[0])analogwires[0]=[];
308                    for(var k=0;k<wire.length;k++)analogwires[0].push(wire[k])
309    /* add analog ground to digital wirelist*/
310                    if(!digitalwires[0])digitalwires.push(analogwires[0]);
311                    net=null;
312                }
313                
314                else if(found<0){
315                    net.pins.push(analogcount);
316                    analogwires.push(wire);
317                    analogcount++;
318                }
319                else{ 
320                    net.pins.push(found);
321                }
322            }
323            else{
324                if(digitalwires.length==0){
325                net.error="no ground node";                      
326                } 
327                var found=this.getconnected(digitalwires,wire);
328                if(found<0){
329                    var v=this.tovector(nodes[j],digitalcount);
330                    net.pins.push(v);
331                    digitalwires.push(wire);
332                    digitalcount++;
333                }
334                else{ 
335                    var v=this.tovector(nodes[j],found);
336                    net.pins.push(v);
337                }
338                
339            }        
340
341        }
342//after all wires are numbered check which ones are plotted
343        if(parts[i].type=="plot"){
344            var point={x:this.getwtxattribute(nodes[0],"x"),y:this.getwtxattribute(nodes[0],"y")};
345            point=this.matrixxform(point,this.parseMatrix(parts[i].elem));
346            var wire=this.followwires(null,point);
347            var found=this.getconnected(analogwires,wire);
348            if(found>-1){trannodes.push(found);}
349            else {
350                var found=this.getconnected(digitalwires,wire);
351                if(found>-1){trannodes.push("a"+found);}
352            }
353        }
354        else if(net!=null)sections.netlist.push(net);
355	}
356//create tran print nodes
357    if(sections.simulation.length==1){
358      for(var i=0;i<trannodes.length;i++){
359	  var command=".print tran"
360	  for(var i=0;i<trannodes.length;i++){
361  /*digital*/
362	      if(trannodes[i].toString().match('a')){
363		  command+=" "+trannodes[i];
364	      }
365  /*analog*/
366	      else{command+=" v("+trannodes[i]+")"}    
367	  }
368	
369      }
370	  if(command!=null){
371	    sections.simulation.unshift(command);
372	    sections.simulation.unshift(".op");
373	  }
374      
375    }
376    if(this.mixedsignals(analogwires,digitalwires)){
377        return {firstdir:[],netlist:[{error:"pin is both analog and digital"}],lastdir:[],plot:[]};
378    }
379    return sections;
380
381}
382/* organizes data into netlist*/
383Schematic.prototype.createnetlist=function(responsefunc){
384    
385	var parts=$$('#webtronics_drawing > g');
386    if(parts.length<1){
387      responsefunc("no parts found\n");
388      return;
389    }
390    var partswtx=this.sortnetlist(this.getwtxdata(parts));
391	if(partswtx[0].type.toLowerCase()!='gnd'){
392	  responsefunc('no ground node');
393	  return;
394	}
395	this.connectwires(partswtx);
396	var spice=".title webtronics\n";
397    var sections=this.getnodes(partswtx);
398
399//dump models into spice	
400    var modelloader={
401     modeltext:"",
402     modelcount:0,
403     responsecount:0,
404     download:function(name){
405	openfile( "../spice/"+ name.split(' ')[1],modelloader.responder);
406	modelloader.modelcount++;
407    },
408    finish:function(){
409      	 spice+=modelloader.modeltext; 
410	 if(sections.simulation.length){
411	  var command=".print tran"
412		  for(var i=0;i<sections.simulation.length;i++){
413			  if(sections.simulation[i]!="")spice+=sections.simulation[i]+"\n";
414		  }
415	  }
416	  if(sections.lastdir.length){
417		  sections.lastdir=sections.lastdir.uniq();
418		  for(var i=0;i<sections.lastdir.length;i++){
419			  if(sections.lastdir[i]!="")spice+=sections.lastdir[i]+"\n";
420		  }
421	  }
422
423	  spice=spice.concat(".end \n");	
424	  var connector=$$('#information > .namewire')
425	  for(var i=0;i<connector.length;i++)connector[i].parentNode.removeChild(connector[i]);
426
427	  responsefunc(spice.toLowerCase());
428    },
429     responder:function(text){
430       modelloader.modeltext+=text;
431       modelloader.responsecount++;
432       if(modelloader.responsecount==modelloader.modelcount){
433	  modelloader.finish();
434	 
435      }       
436    }
437    }
438	if(sections.netlist.length){
439        var command="";
440	    for(var i=0;i<sections.netlist.length;i++){
441	      if(sections.netlist[i].error!=""){
442		  spice+=sections.netlist[i].error+'\n';
443		  continue;
444	      }
445	      command=sections.netlist[i].partid;
446	      for(var j=0;j<sections.netlist[i].pins.length;j++)command+=" "+sections.netlist[i].pins[j];
447	      command+=" "+sections.netlist[i].model;
448	      if(command!="")spice+=command+'\n';
449	    }
450	}
451
452	if(sections.firstdir.length){
453	    sections.firstdir=sections.firstdir.uniq();
454		for(var i=0;i<sections.firstdir.length;i++){
455			console.log(sections.firstdir[i]);
456			if(sections.firstdir[i].length){
457			  modelloader.download(sections.firstdir[i]);
458			}
459		}
460	}
461	else modelloader.finish();
462
463
464  
465}
466
467
468Schematic.prototype.followwires=function(wirelist,pin){
469	if(wirelist==null)wirelist=[];
470	var points=[];
471	points.push(pin);	
472	var lines =$$('#webtronics_drawing > line, #information > .namewire');
473	for(var i =0 ;i<lines.length;i++){
474		var point1={x:lines[i].getAttribute('x1')-0,y:lines[i].getAttribute('y1')-0};
475		var point2={x:lines[i].getAttribute('x2')-0,y:lines[i].getAttribute('y2')-0};
476		if(wirelist.indexOf(lines[i])<0){		
477			if(this.ispoint(point1,pin)){
478				wirelist.push(lines[i]);
479				var p=this.followwires(wirelist,point2);
480				for(var j=0;j<p.length;j++)points.push(p[j]);				
481			}
482			else if(this.ispoint(point2,pin)){
483				wirelist.push(lines[i]);
484				var p=this.followwires(wirelist,point1);
485				for(var j=0;j<p.length;j++)points.push(p[j]);				
486			}
487		}
488	}
489	return points;
490}
491
492Schematic.prototype.addconnects=function(elem,pin){
493	var pins=this.getconnects(elem);
494	var str;
495	if(!pins){
496		str=pin.x+','+pin.y;
497		elem.setAttribute('connects',str);
498	}
499	else {
500		str=this.writeconnects(pins);
501		str+=';'+pin.x+','+pin.y;
502		elem.setAttribute('connects',str);
503	}
504
505}
506
507
508Schematic.prototype.writeconnects=function(pins){
509
510	var str=[];
511	
512	for(var i=0;i<pins.length;i++){
513		str[i] = pins[i].x +','+pins[i].y;
514	}
515	return str.join(';'); 
516}
517
518Schematic.prototype.isconnect=function(pin,radius,x,y){
519	return ((pin.x+radius)>x)&&((pin.x-radius)<x)&&
520		((pin.y+radius)>y)&&((pin.y-radius)<y);
521}
522
523
524Schematic.prototype.isconnects=function(radius,x,y){
525
526	var parts=this.drawing.childNodes;
527	for(var i=0; i<parts.length; i++){
528		if(parts[i].tagName=='g'){
529			var pins=this.getconnects(parts[i]);
530			if(pins){
531				for(var j=0;j<pins.length;j++){
532					if(this.isconnect(pins[j],radius,x,y)){
533						return pins[j];
534					}
535				}
536			}
537		}
538	}
539	return null;
540}
541
542
543
544
545Schematic.prototype.showallconnects=function(){
546	if(this.connections){	
547		var parts=$$('#webtronics_drawing > g');
548    	this.connectwires(this.getwtxdata(parts));
549		for(var i=0 ;i<parts.length;i++){
550            var nodes=this.getwtxtagname(parts[i],"node");
551            
552			for(var j=0;j<nodes.length;j++){
553                var x=this.getwtxattribute(nodes[j],"x");
554                var y=this.getwtxattribute(nodes[j],"y");
555                var point=this.matrixxform({x:x,y:y},this.parseMatrix(parts[i]));
556
557                if(nodes[j].parentNode.tagName=="wtx:analog"){
558			        var circle=this.createdot('red',point.x,point.y);
559			        circle.setAttribute('class',"schematic_connector");
560			        this.info.appendChild(circle);
561                }
562                else{
563                    var rect=this.createrect('green',100,point.x-3,point.y-3,6,6);
564                    rect.setAttribute('class',"schematic_connector");
565                    this.info.appendChild(rect);
566                }
567
568
569            }
570		}
571	}
572}
573
574Schematic.prototype.hideconnects=function(){
575
576	var connector=$$('#information .schematic_connector,#information .namewire')
577	for(var i=0;i<connector.length;i++)connector[i].parentNode.removeChild(connector[i]);
578}
579
580
581