updated schematic tool files
This commit is contained in:
67
js/cktsim.js
67
js/cktsim.js
@@ -44,6 +44,7 @@ cktsim = (function() {
|
||||
|
||||
this.devices = []; // list of devices
|
||||
this.device_map = new Array(); // map name -> device
|
||||
this.voltage_sources = []; // list of voltage sources
|
||||
|
||||
this.finalized = false;
|
||||
this.diddc = false;
|
||||
@@ -104,10 +105,14 @@ cktsim = (function() {
|
||||
var type = component[0];
|
||||
|
||||
// ignore wires, ground connections, scope probes and view info
|
||||
if (type == 'view' || type == 'w' || type == 'g' || type == 's' || type == 'L') continue;
|
||||
if (type == 'view' || type == 'w' || type == 'g' || type == 's' || type == 'L') {
|
||||
continue;
|
||||
}
|
||||
|
||||
var properties = component[2];
|
||||
var name = properties['name'];
|
||||
if (name==undefined || name=='')
|
||||
name = '_' + properties['_json_'].toString();
|
||||
|
||||
// convert node names to circuit indicies
|
||||
var connections = component[3];
|
||||
@@ -134,11 +139,9 @@ cktsim = (function() {
|
||||
else if (type == 'o') // op amp
|
||||
this.opamp(connections[0],connections[1],connections[2],properties['A'],name);
|
||||
else if (type == 'n') // n fet
|
||||
this.n(connections[0],connections[1],connections[2],
|
||||
properties['W/L'],name);
|
||||
this.n(connections[0],connections[1],connections[2],properties['W/L'],name);
|
||||
else if (type == 'p') // p fet
|
||||
this.p(connections[0],connections[1],connections[2],
|
||||
properties['W/L'],name);
|
||||
this.p(connections[0],connections[1],connections[2],properties['W/L'],name);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -214,10 +217,16 @@ cktsim = (function() {
|
||||
this.diddc = true;
|
||||
// create solution dictionary
|
||||
var result = new Array();
|
||||
// capture node voltages
|
||||
for (var name in this.node_map) {
|
||||
var index = this.node_map[name];
|
||||
result[name] = (index == -1) ? 0 : this.solution[index];
|
||||
}
|
||||
// capture branch currents from voltage sources
|
||||
for (var i = this.voltage_sources.length - 1; i >= 0; --i) {
|
||||
var v = this.voltage_sources[i];
|
||||
result['I('+v.name+')'] = this.solution[v.branch];
|
||||
}
|
||||
return result;
|
||||
}
|
||||
}
|
||||
@@ -457,6 +466,12 @@ cktsim = (function() {
|
||||
var index = this.node_map[name];
|
||||
result[name] = (index == -1) ? 0 : response[index];
|
||||
}
|
||||
// capture branch currents from voltage sources
|
||||
for (var i = this.voltage_sources.length - 1; i >= 0; --i) {
|
||||
var v = this.voltage_sources[i];
|
||||
result['I('+v.name+')'] = response[v.branch];
|
||||
}
|
||||
|
||||
result['time'] = response[this.N];
|
||||
return result;
|
||||
}
|
||||
@@ -537,6 +552,7 @@ cktsim = (function() {
|
||||
Circuit.prototype.add_device = function(d,name) {
|
||||
// Add device to list of devices and to device map
|
||||
this.devices.push(d);
|
||||
d.name = name;
|
||||
if (name) {
|
||||
if (this.device_map[name] === undefined)
|
||||
this.device_map[name] = d;
|
||||
@@ -599,6 +615,7 @@ cktsim = (function() {
|
||||
Circuit.prototype.v = function(n1,n2,v,name) {
|
||||
var branch = this.node(undefined,T_CURRENT);
|
||||
var d = new VSource(n1,n2,branch,v);
|
||||
this.voltage_sources.push(d);
|
||||
return this.add_device(d, name);
|
||||
}
|
||||
|
||||
@@ -1029,9 +1046,11 @@ cktsim = (function() {
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
// argument is a string describing the source's value (see comments for details)
|
||||
// source types: dc,step,square,triangle,sin,pulse,pwl,pwlr
|
||||
// source types: dc,step,square,triangle,sin,pulse,pwl,pwl_repeating
|
||||
|
||||
// returns an object with the following attributes:
|
||||
// fun -- name of source function
|
||||
// args -- list of argument values
|
||||
// value(t) -- compute source value at time t
|
||||
// inflection_point(t) -- compute time after t when a time point is needed
|
||||
// dc -- value at time 0
|
||||
@@ -1071,32 +1090,35 @@ cktsim = (function() {
|
||||
// post-processing for constant sources
|
||||
// dc(v)
|
||||
if (src.fun == 'dc') {
|
||||
var value = src.args[0];
|
||||
if (value === undefined) value = 0;
|
||||
src.value = function(t) { return value; } // closure
|
||||
var v = arg_value(src.args,0,0);
|
||||
src.args = [v];
|
||||
src.value = function(t) { return v; } // closure
|
||||
}
|
||||
|
||||
// post-processing for step sources
|
||||
// step(v_init,v_plateau,t_delay,t_rise,t_fall)
|
||||
// step(v_init,v_plateau,t_delay,t_rise)
|
||||
else if (src.fun == 'step') {
|
||||
var v1 = arg_value(src.args,0,0); // default init value: 0V
|
||||
var v2 = arg_value(src.args,1,1); // default plateau value: 1V
|
||||
var td = Math.max(0,arg_value(src.args,2,0)); // time step starts
|
||||
var tr = Math.abs(arg_value(src.args,3,1e-9)); // default rise time: 1ns
|
||||
src.args = [v1,v2,td,tr]; // remember any defaulted values
|
||||
pwl_source(src,[td,v1,td+tr,v2],false);
|
||||
}
|
||||
|
||||
// post-processing for square wave
|
||||
// square(v_init,v_plateau,t_period)
|
||||
// square(v_init,v_plateau,freq)
|
||||
else if (src.fun == 'square') {
|
||||
var v1 = arg_value(src.args,0,0); // default init value: 0V
|
||||
var v2 = arg_value(src.args,1,1); // default plateau value: 1V
|
||||
var freq = Math.abs(arg_value(src.args,2,1)); // default frequency: 1s
|
||||
var freq = Math.abs(arg_value(src.args,2,1)); // default frequency: 1Hz
|
||||
src.args = [v1,v2,freq]; // remember any defaulted values
|
||||
|
||||
var per = freq == 0 ? Infinity : 1/freq;
|
||||
var t_change = 0.01 * per; // rise and fall time
|
||||
var t_pw = 0.49 * per; // half the cycle minus rise and fall time
|
||||
pwl_source(src,[0,v1,t_change,v2,t_change+t_pw,v2,t_change+t_pw+t_change,v1,per,v1],true);
|
||||
pwl_source(src,[0,v1,t_change,v2,t_change+t_pw,
|
||||
v2,t_change+t_pw+t_change,v1,per,v1],true);
|
||||
}
|
||||
|
||||
// post-processing for triangle
|
||||
@@ -1105,6 +1127,7 @@ cktsim = (function() {
|
||||
var v1 = arg_value(src.args,0,0); // default init value: 0V
|
||||
var v2 = arg_value(src.args,1,1); // default plateau value: 1V
|
||||
var freq = Math.abs(arg_value(src.args,2,1)); // default frequency: 1s
|
||||
src.args = [v1,v2,freq]; // remember any defaulted values
|
||||
|
||||
var per = freq == 0 ? Infinity : 1/freq;
|
||||
pwl_source(src,[0,v1,per/2,v2,per,v1],true);
|
||||
@@ -1112,8 +1135,8 @@ cktsim = (function() {
|
||||
|
||||
// post-processing for pwl and pwlr sources
|
||||
// pwl[r](t1,v1,t2,v2,...)
|
||||
else if (src.fun == 'pwl' || src.fun == 'pwlr') {
|
||||
pwl_source(src,src.args,src.fun == 'pwlr');
|
||||
else if (src.fun == 'pwl' || src.fun == 'pwl_repeating') {
|
||||
pwl_source(src,src.args,src.fun == 'pwl_repeating');
|
||||
}
|
||||
|
||||
// post-processing for pulsed sources
|
||||
@@ -1122,18 +1145,18 @@ cktsim = (function() {
|
||||
var v1 = arg_value(src.args,0,0); // default init value: 0V
|
||||
var v2 = arg_value(src.args,1,1); // default plateau value: 1V
|
||||
var td = Math.max(0,arg_value(src.args,2,0)); // time pulse starts
|
||||
|
||||
var tr = Math.abs(arg_value(src.args,3,1e-9)); // default rise time: 1ns
|
||||
var tf = Math.abs(arg_value(src.args,4,1e-9)); // default rise time: 1ns
|
||||
var pw = Math.abs(arg_value(src.args,5,1e9)); // default pulse width: "infinite"
|
||||
var per = Math.abs(arg_value(src.args,6,1e9)); // default period: "infinite"
|
||||
src.args = [v1,v2,td,tr,tf,pw,per];
|
||||
|
||||
var t1 = td; // time when v1 -> v2 transition starts
|
||||
var t2 = t1 + tr; // time when v1 -> v2 transition ends
|
||||
var t3 = t2 + pw; // time when v2 -> v1 transition starts
|
||||
var t4 = t3 + tf; // time when v2 -> v1 transition ends
|
||||
|
||||
pwl_source(src,[t1,v1,t2,v2,t3,v2,t4,v1,per,v1],true);
|
||||
pwl_source(src,[t1,v1, t2,v2, t3,v2, t4,v1, per,v1],true);
|
||||
}
|
||||
|
||||
// post-processing for sinusoidal sources
|
||||
@@ -1144,16 +1167,14 @@ cktsim = (function() {
|
||||
var freq = Math.abs(arg_value(src.args,2,1)); // default frequency: 1Hz
|
||||
var td = Math.max(0,arg_value(src.args,3,0)); // default time delay: 0sec
|
||||
var phase = arg_value(src.args,4,0); // default phase offset: 0 degrees
|
||||
src.args = [voffset,va,freq,td,phase];
|
||||
|
||||
phase /= 360.0;
|
||||
|
||||
// return value of source at time t
|
||||
src.value = function(t) { // closure
|
||||
if (t < td) return voffset + va*Math.sin(2*Math.PI*phase);
|
||||
else {
|
||||
var val = voffset + va*Math.sin(2*Math.PI*(freq*(t - td) + phase));
|
||||
return val;
|
||||
}
|
||||
else return voffset + va*Math.sin(2*Math.PI*(freq*(t - td) + phase));
|
||||
}
|
||||
|
||||
// return time of next inflection point after time t
|
||||
@@ -1163,9 +1184,6 @@ cktsim = (function() {
|
||||
}
|
||||
}
|
||||
|
||||
// to do:
|
||||
// post-processing for piece-wise linear sources
|
||||
|
||||
// object has all the necessary info to compute the source value and inflection points
|
||||
src.dc = src.value(0); // DC value is value at time 0
|
||||
return src;
|
||||
@@ -1531,6 +1549,7 @@ cktsim = (function() {
|
||||
var module = {
|
||||
'Circuit': Circuit,
|
||||
'parse_number': parse_number,
|
||||
'parse_source': parse_source,
|
||||
}
|
||||
return module;
|
||||
}());
|
||||
|
||||
309
js/schematic.js
309
js/schematic.js
@@ -594,8 +594,9 @@ schematic = (function() {
|
||||
var json = [];
|
||||
|
||||
// output all the components/wires in the diagram
|
||||
for (var i = this.components.length - 1; i >=0; --i)
|
||||
json.push(this.components[i].json());
|
||||
var n = this.components.length;
|
||||
for (var i = 0; i < n; i++)
|
||||
json.push(this.components[i].json(i));
|
||||
|
||||
// capture the current view parameters
|
||||
json.push(['view',this.origin_x,this.origin_y,this.scale,
|
||||
@@ -932,6 +933,10 @@ schematic = (function() {
|
||||
// for each electrical node
|
||||
for (var location in this.connection_points)
|
||||
(this.connection_points[location])[0].display_voltage(c,temp);
|
||||
|
||||
// let components display branch current info if available
|
||||
for (var i = this.components.length - 1; i >= 0; --i)
|
||||
this.components[i].display_current(c,temp)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -980,9 +985,6 @@ schematic = (function() {
|
||||
c.fillText(text,(x - this.origin_x) * this.scale,(y - this.origin_y) * this.scale);
|
||||
}
|
||||
|
||||
HTMLCanvasElement.prototype.totalOffset = function(){
|
||||
}
|
||||
|
||||
// add method to canvas to compute relative coords for event
|
||||
HTMLCanvasElement.prototype.relMouseCoords = function(event){
|
||||
// run up the DOM tree to figure out coords for top,left of canvas
|
||||
@@ -1678,8 +1680,9 @@ schematic = (function() {
|
||||
return [vmin,vmax,1.0/scale];
|
||||
}
|
||||
|
||||
function engineering_notation(n,nplaces) {
|
||||
function engineering_notation(n,nplaces,trim) {
|
||||
if (n == 0) return("0");
|
||||
if (trim == undefined) trim = true;
|
||||
|
||||
var sign = n < 0 ? -1 : 1;
|
||||
var log10 = Math.log(sign*n)/Math.LN10;
|
||||
@@ -1694,8 +1697,10 @@ schematic = (function() {
|
||||
if (nplaces > 0) {
|
||||
endindex += nplaces + 1;
|
||||
if (endindex > mlen) endindex = mlen;
|
||||
while (mstring.charAt(endindex-1) == '0') endindex -= 1;
|
||||
if (mstring.charAt(endindex-1) == '.') endindex -= 1;
|
||||
if (trim) {
|
||||
while (mstring.charAt(endindex-1) == '0') endindex -= 1;
|
||||
if (mstring.charAt(endindex-1) == '.') endindex -= 1;
|
||||
}
|
||||
}
|
||||
if (endindex < mlen)
|
||||
mstring = mstring.substring(0,endindex);
|
||||
@@ -1717,6 +1722,9 @@ schematic = (function() {
|
||||
return n.toString();
|
||||
}
|
||||
|
||||
var grid_pattern = [1,2];
|
||||
var cursor_pattern = [5,5];
|
||||
|
||||
// x_values is an array of x coordinates for each of the plots
|
||||
// y_values is an array of [color, value_array], one entry for each plot
|
||||
Schematic.prototype.graph = function(x_values,y_values,x_legend,y_legend) {
|
||||
@@ -1727,7 +1735,6 @@ schematic = (function() {
|
||||
var right_margin = 25;
|
||||
var bottom_margin = 45;
|
||||
var tick_length = 5;
|
||||
var pattern = [1,2];
|
||||
|
||||
var w = pwidth + left_margin + right_margin;
|
||||
var h = pheight + top_margin + bottom_margin;
|
||||
@@ -1735,7 +1742,7 @@ schematic = (function() {
|
||||
var canvas = document.createElement('canvas');
|
||||
canvas.width = w;
|
||||
canvas.height = h;
|
||||
|
||||
|
||||
// the graph itself will be drawn here and this image will be copied
|
||||
// onto canvas, where it can be overlayed with mouse cursors, etc.
|
||||
var bg_image = document.createElement('canvas');
|
||||
@@ -1779,7 +1786,7 @@ schematic = (function() {
|
||||
c.moveTo(temp,top_margin);
|
||||
c.lineTo(temp,end);
|
||||
} else
|
||||
c.dashedLineTo(temp,top_margin,temp,end,pattern);
|
||||
c.dashedLineTo(temp,top_margin,temp,end,grid_pattern);
|
||||
c.stroke();
|
||||
|
||||
// tick mark
|
||||
@@ -1821,7 +1828,7 @@ schematic = (function() {
|
||||
c.moveTo(left_margin,temp);
|
||||
c.lineTo(left_margin + pwidth,temp);
|
||||
} else
|
||||
c.dashedLineTo(left_margin,temp,left_margin + pwidth,temp,pattern);
|
||||
c.dashedLineTo(left_margin,temp,left_margin + pwidth,temp,grid_pattern);
|
||||
c.stroke();
|
||||
|
||||
// tick mark
|
||||
@@ -1864,6 +1871,27 @@ schematic = (function() {
|
||||
c.fillText(y_legend,0,0);
|
||||
c.restore();
|
||||
|
||||
// save info need for interactions with the graph
|
||||
canvas.x_values = x_values;
|
||||
canvas.y_values = y_values;
|
||||
canvas.x_legend = x_legend;
|
||||
canvas.y_legend = y_legend;
|
||||
canvas.x_min = x_min;
|
||||
canvas.x_scale = x_scale;
|
||||
canvas.y_min = y_min;
|
||||
canvas.y_scale = y_scale;
|
||||
canvas.left_margin = left_margin;
|
||||
canvas.top_margin = top_margin;
|
||||
canvas.pwidth = pwidth;
|
||||
canvas.pheight = pheight;
|
||||
canvas.tick_length = tick_length;
|
||||
|
||||
canvas.cursor_x = undefined;
|
||||
canvas.sch = this;
|
||||
|
||||
// do something useful when user mouses over graph
|
||||
canvas.addEventListener('mousemove',graph_mouse_move,false);
|
||||
|
||||
// return our masterpiece
|
||||
redraw_plot(canvas);
|
||||
return canvas;
|
||||
@@ -1883,9 +1911,73 @@ schematic = (function() {
|
||||
return min;
|
||||
}
|
||||
|
||||
function redraw_plot(canvas) {
|
||||
var c = canvas.getContext('2d');
|
||||
c.drawImage(canvas.bg_image,0,0);
|
||||
function redraw_plot(graph) {
|
||||
var c = graph.getContext('2d');
|
||||
c.drawImage(graph.bg_image,0,0);
|
||||
|
||||
if (graph.cursor_x != undefined) {
|
||||
// draw dashed vertical marker that follows mouse
|
||||
var x = graph.left_margin + graph.cursor_x;
|
||||
var end_y = graph.top_margin + graph.pheight + graph.tick_length;
|
||||
c.strokeStyle = grid_style;
|
||||
c.lineWidth = 1;
|
||||
c.beginPath();
|
||||
c.dashedLineTo(x,graph.top_margin,x,end_y,cursor_pattern);
|
||||
c.stroke();
|
||||
|
||||
// add x label at bottom of marker
|
||||
var graph_x = graph.cursor_x/graph.x_scale + graph.x_min;
|
||||
c.font = '10pt sans-serif';
|
||||
c.textAlign = 'center';
|
||||
c.textBaseline = 'top';
|
||||
c.fillStyle = background_style;
|
||||
c.fillText('\u2588\u2588\u2588\u2588\u2588',x,end_y);
|
||||
c.fillStyle = normal_style;
|
||||
c.fillText(engineering_notation(graph_x,3,false),x,end_y);
|
||||
|
||||
// compute which points marker is between
|
||||
var x_values = graph.x_values;
|
||||
var len = x_values.length;
|
||||
var index = 0;
|
||||
while (index < len && graph_x >= x_values[index]) index += 1;
|
||||
var x1 = (index == 0) ? x_values[0] : x_values[index-1];
|
||||
var x2 = x_values[index];
|
||||
|
||||
// for each plot, interpolate and output value at intersection with marker
|
||||
c.textAlign = 'left';
|
||||
var tx = graph.left_margin + 4;
|
||||
var ty = graph.top_margin;
|
||||
for (var plot = 0; plot < graph.y_values.length; plot++) {
|
||||
var values = graph.y_values[plot][1];
|
||||
|
||||
// interpolate signal value at graph_x using values[index-1] and values[index]
|
||||
var y1 = (index == 0) ? values[0] : values[index-1];
|
||||
var y2 = values[index];
|
||||
var y = y1;
|
||||
if (graph_x != x1) y += (graph_x - x1)*(y2 - y1)/(x2 - x1);
|
||||
|
||||
// annotate plot with value of signal at marker
|
||||
c.fillStyle = element_style;
|
||||
c.fillText('\u2588\u2588\u2588\u2588\u2588',tx-3,ty);
|
||||
c.fillStyle = probe_colors_rgb[graph.y_values[plot][0]];
|
||||
c.fillText(engineering_notation(y,3,false),tx,ty);
|
||||
ty += 14;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function graph_mouse_move(event) {
|
||||
if (!event) event = window.event;
|
||||
var g = (window.event) ? event.srcElement : event.target;
|
||||
|
||||
g.relMouseCoords(event);
|
||||
// not sure yet where the 3,-3 offset correction comes from (borders? padding?)
|
||||
var gx = g.mouse_x - g.left_margin - 3;
|
||||
var gy = g.pheight - (g.mouse_y - g.top_margin) + 3;
|
||||
if (gx >= 0 && gx <= g.pwidth && gy >=0 && gy <= g.pheight) g.cursor_x = gx;
|
||||
else g.cursor_x = undefined;
|
||||
|
||||
redraw_plot(g);
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
@@ -2112,7 +2204,9 @@ schematic = (function() {
|
||||
this.connections = [];
|
||||
}
|
||||
|
||||
Component.prototype.json = function() {
|
||||
Component.prototype.json = function(index) {
|
||||
this.properties['_json_'] = index; // remember where we are in the JSON list
|
||||
|
||||
var props = {};
|
||||
for (var p in this.properties) props[p] = this.properties[p];
|
||||
|
||||
@@ -2343,7 +2437,9 @@ schematic = (function() {
|
||||
// make an <input> widget for each property
|
||||
var fields = new Array();
|
||||
for (var i in this.properties)
|
||||
fields[i] = build_input('text',10,this.properties[i]);
|
||||
// underscore at beginning of property name => system property
|
||||
if (i.charAt(0) != '_')
|
||||
fields[i] = build_input('text',10,this.properties[i]);
|
||||
|
||||
var content = build_table(fields);
|
||||
content.fields = fields;
|
||||
@@ -2383,6 +2479,10 @@ schematic = (function() {
|
||||
}
|
||||
}
|
||||
|
||||
// default behavior: nothing to display for DC analysis
|
||||
Component.prototype.display_current = function(c,vmap) {
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Connection point
|
||||
@@ -2507,7 +2607,7 @@ schematic = (function() {
|
||||
return '<Wire ('+this.x+','+this.y+') ('+(this.x+this.dx)+','+(this.y+this.dy)+')>';
|
||||
}
|
||||
|
||||
Wire.prototype.json = function() {
|
||||
Wire.prototype.json = function(index) {
|
||||
var json = ['w',[this.x, this.y, this.x+this.dx, this.y+this.dy]];
|
||||
return json;
|
||||
}
|
||||
@@ -3024,14 +3124,18 @@ schematic = (function() {
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
||||
function Source(x,y,rotation,name,type,value) {
|
||||
Component.call(this,type,x,y,rotation);
|
||||
this.properties['name'] = name;
|
||||
this.properties['value'] = value ? value : '1';
|
||||
if (value == undefined) value = 'dc(1)';
|
||||
this.properties['value'] = value;
|
||||
this.add_connection(0,0);
|
||||
this.add_connection(0,48);
|
||||
this.bounding_box = [-12,0,12,48];
|
||||
this.update_coords();
|
||||
|
||||
this.content = document.createElement('div'); // used by edit_properties
|
||||
}
|
||||
Source.prototype = new Component();
|
||||
Source.prototype.constructor = Source;
|
||||
@@ -3068,10 +3172,141 @@ schematic = (function() {
|
||||
this.draw_text(c,this.properties['value'],13,24,3,property_size);
|
||||
}
|
||||
|
||||
Source.prototype.clone = function(x,y) {
|
||||
return new Source(x,y,this.rotation,this.properties['name'],this.type,this.properties['value']);
|
||||
// map source function name to labels for each source parameter
|
||||
source_functions = {
|
||||
'dc': ['DC value'],
|
||||
|
||||
'step': ['Initial value',
|
||||
'Plateau value',
|
||||
'Delay until step (secs)',
|
||||
'Rise time (secs)'],
|
||||
|
||||
'square': ['Initial value',
|
||||
'Plateau value',
|
||||
'Frequency (Hz)'],
|
||||
|
||||
'triangle': ['Initial value',
|
||||
'Plateau value',
|
||||
'Frequency (Hz)'],
|
||||
|
||||
'pwl': ['Comma-separated list of alternating times and values'],
|
||||
|
||||
'pwl_repeating': ['Comma-separated list of alternating times and values'],
|
||||
|
||||
'pulse': ['Initial value',
|
||||
'Plateau value',
|
||||
'Delay until pulse (secs)',
|
||||
'Time for first transition (secs)',
|
||||
'Time for second transition (secs)',
|
||||
'Pulse width (secs)',
|
||||
'Period (secs)'],
|
||||
|
||||
'sin': ['Offset value',
|
||||
'Amplitude',
|
||||
'Frequency (Hz)',
|
||||
'Delay until sin starts (secs)',
|
||||
'Phase offset (degrees)'],
|
||||
}
|
||||
|
||||
// build property editor div
|
||||
Source.prototype.build_content = function(src) {
|
||||
// make an <input> widget for each property
|
||||
var fields = []
|
||||
fields['name'] = build_input('text',10,this.properties['name']);
|
||||
|
||||
if (src == undefined) {
|
||||
fields['value'] = this.properties['value'];
|
||||
} else {
|
||||
// fancy version: add select tag for source type
|
||||
var src_types = [];
|
||||
for (var t in source_functions) src_types.push(t);
|
||||
var type_select = build_select(src_types,src.fun);
|
||||
type_select.component = this;
|
||||
type_select.addEventListener('change',source_type_changed,false)
|
||||
fields['type'] = type_select;
|
||||
|
||||
if (src.fun == 'pwl' || src.run == 'pwl_repeating') {
|
||||
var v = '';
|
||||
var first = true;
|
||||
for (var i = 0; i < src.args.length; i++) {
|
||||
if (first) first = false;
|
||||
else v += ',';
|
||||
v += engineering_notation(src.args[i],3);
|
||||
if (i % 2 == 0) v += 's';
|
||||
}
|
||||
fields[source_functions[src.fun][0]] = build_input('text',30,v);
|
||||
} else {
|
||||
// followed separate input tag for each parameter
|
||||
var labels = source_functions[src.fun];
|
||||
for (var i = 0; i < labels.length; i++) {
|
||||
var v = engineering_notation(src.args[i],3);
|
||||
fields[labels[i]] = build_input('text',10,v);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
var div = this.content;
|
||||
if (div.hasChildNodes())
|
||||
div.removeChild(div.firstChild); // remove table of input fields
|
||||
div.appendChild(build_table(fields));
|
||||
div.fields = fields;
|
||||
div.component = this;
|
||||
return div;
|
||||
}
|
||||
|
||||
function source_type_changed(event) {
|
||||
if (!event) event = window.event;
|
||||
var select = (window.event) ? event.srcElement : event.target;
|
||||
|
||||
// see where to get source parameters from
|
||||
var type = select.options[select.selectedIndex].value;
|
||||
var src = undefined;
|
||||
if (this.src != undefined && type == this.src.fun)
|
||||
src = this.src;
|
||||
else if (typeof cktsim != 'undefined')
|
||||
src = cktsim.parse_source(type+'()');
|
||||
|
||||
select.component.build_content(src);
|
||||
}
|
||||
|
||||
Source.prototype.edit_properties = function(x,y) {
|
||||
if (this.near(x,y)) {
|
||||
this.src = undefined;
|
||||
if (typeof cktsim != 'undefined')
|
||||
this.src = cktsim.parse_source(this.properties['value']);
|
||||
var content = this.build_content(this.src);
|
||||
|
||||
this.sch.dialog('Edit Properties',content,function(content) {
|
||||
var c = content.component;
|
||||
var fields = content.fields;
|
||||
|
||||
var first = true;
|
||||
var value = '';
|
||||
for (var label in fields) {
|
||||
if (label == 'name')
|
||||
c.properties['name'] = fields['name'].value;
|
||||
else if (label == 'value') {
|
||||
// if unknown source type
|
||||
value = fields['value'].value;
|
||||
c.sch.redraw_background();
|
||||
return;
|
||||
} else if (label == 'type') {
|
||||
var select = fields['type'];
|
||||
value = select.options[select.selectedIndex].value + '(';
|
||||
} else {
|
||||
if (first) first = false;
|
||||
else value += ',';
|
||||
value += fields[label].value;
|
||||
}
|
||||
}
|
||||
c.properties['value'] = value + ')';
|
||||
c.sch.redraw_background();
|
||||
});
|
||||
return true;
|
||||
} else return false;
|
||||
}
|
||||
|
||||
|
||||
function VSource(x,y,rotation,name,value) {
|
||||
Source.call(this,x,y,rotation,name,'v',value);
|
||||
this.type = 'v';
|
||||
@@ -3081,6 +3316,32 @@ schematic = (function() {
|
||||
VSource.prototype.toString = Source.prototype.toString;
|
||||
VSource.prototype.draw = Source.prototype.draw;
|
||||
VSource.prototype.clone = Source.prototype.clone;
|
||||
VSource.prototype.build_content = Source.prototype.build_content;
|
||||
VSource.prototype.edit_properties = Source.prototype.edit_properties;
|
||||
|
||||
// display current for DC analysis
|
||||
VSource.prototype.display_current = function(c,vmap) {
|
||||
var name = this.properties['name'];
|
||||
var label = 'I(' + (name ? name : '_' + this.properties['_json_']) + ')';
|
||||
var v = vmap[label];
|
||||
if (v != undefined) {
|
||||
// first draw some solid blocks in the background
|
||||
c.globalAlpha = 0.85;
|
||||
this.draw_text(c,'\u2588\u2588\u2588',0,24,4,annotation_size,element_style);
|
||||
c.globalAlpha = 1.0;
|
||||
|
||||
// display the node voltage at this connection point
|
||||
var i = engineering_notation(v,2) + 'A';
|
||||
this.draw_text(c,i,0,24,4,annotation_size,annotation_style);
|
||||
|
||||
// only display each current once
|
||||
delete vmap[label];
|
||||
}
|
||||
}
|
||||
|
||||
VSource.prototype.clone = function(x,y) {
|
||||
return new VSource(x,y,this.rotation,this.properties['name'],this.properties['value']);
|
||||
}
|
||||
|
||||
function ISource(x,y,rotation,name,value) {
|
||||
Source.call(this,x,y,rotation,name,'i',value);
|
||||
@@ -3091,6 +3352,12 @@ schematic = (function() {
|
||||
ISource.prototype.toString = Source.prototype.toString;
|
||||
ISource.prototype.draw = Source.prototype.draw;
|
||||
ISource.prototype.clone = Source.prototype.clone;
|
||||
ISource.prototype.build_content = Source.prototype.build_content;
|
||||
ISource.prototype.edit_properties = Source.prototype.edit_properties;
|
||||
|
||||
ISource.prototype.clone = function(x,y) {
|
||||
return new ISource(x,y,this.rotation,this.properties['name'],this.properties['value']);
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
|
||||
Reference in New Issue
Block a user