/webtronics/script/connections.js
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