/*
Copyright (C) Paul Falstad and Iain Sharp
This file is part of CircuitJS1.
CircuitJS1 is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 2 of the License, or
(at your option) any later version.
CircuitJS1 is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with CircuitJS1. If not, see <http://www.gnu.org/licenses/>.
*/
package com.lushprojects.circuitjs1.client;
//import java.awt.*;
//import java.util.StringTokenizer;
// Silicon-Controlled Rectifier
// 3 nodes, 1 internal node
// 0 = anode, 1 = cathode, 2 = gate
// 0, 3 = variable resistor
// 3, 2 = diode
// 2, 1 = 50 ohm resistor
class SCRElm extends CircuitElm {
final int anode = 0;
final int cnode = 1;
final int gnode = 2;
final int inode = 3;
Diode diode;
public SCRElm(int xx, int yy) {
super(xx, yy);
setDefaults();
setup();
}
public SCRElm(int xa, int ya, int xb, int yb, int f,
StringTokenizer st) {
super(xa, ya, xb, yb, f);
setDefaults();
try {
lastvac = new Double(st.nextToken()).doubleValue();
lastvag = new Double(st.nextToken()).doubleValue();
volts[anode] = 0;
volts[cnode] = -lastvac;
volts[gnode] = -lastvag;
triggerI = new Double(st.nextToken()).doubleValue();
holdingI = new Double(st.nextToken()).doubleValue();
cresistance = new Double(st.nextToken()).doubleValue();
} catch (Exception e) {
}
setup();
}
void setDefaults() {
cresistance = 50;
holdingI = .0082;
triggerI = .01;
}
void setup() {
diode = new Diode(sim);
diode.setup(.8, 0);
}
boolean nonLinear() { return true; }
void reset() {
volts[anode] = volts[cnode] = volts[gnode] = 0;
diode.reset();
lastvag = lastvac = curcount_a = curcount_c = curcount_g = 0;
}
int getDumpType() { return 177; }
String dump() {
return super.dump() + " " + (volts[anode]-volts[cnode]) + " " +
(volts[anode]-volts[gnode]) + " " + triggerI + " "+ holdingI + " " +
cresistance;
}
double ia, ic, ig, curcount_a, curcount_c, curcount_g;
double lastvac, lastvag;
double cresistance, triggerI, holdingI;
final int hs = 8;
Polygon poly;
Point cathode[], gate[];
void setPoints() {
super.setPoints();
int dir = 0;
if (abs(dx) > abs(dy)) {
dir = -sign(dx)*sign(dy);
point2.y = point1.y;
} else {
dir = sign(dy)*sign(dx);
point2.x = point1.x;
}
if (dir == 0)
dir = 1;
calcLeads(16);
cathode = newPointArray(2);
Point pa[] = newPointArray(2);
interpPoint2(lead1, lead2, pa[0], pa[1], 0, hs);
interpPoint2(lead1, lead2, cathode[0], cathode[1], 1, hs);
poly = createPolygon(pa[0], pa[1], lead2);
gate = newPointArray(2);
double leadlen = (dn-16)/2;
int gatelen = sim.gridSize;
gatelen += leadlen % sim.gridSize;
if (leadlen < gatelen) {
x2 = x; y2 = y;
return;
}
interpPoint(lead2, point2, gate[0], gatelen/leadlen, gatelen*dir);
interpPoint(lead2, point2, gate[1], gatelen/leadlen, sim.gridSize*2*dir);
gate[1].x = sim.snapGrid(gate[1].x);
gate[1].y = sim.snapGrid(gate[1].y);
}
void draw(Graphics g) {
setBbox(point1, point2, hs);
adjustBbox(gate[0], gate[1]);
double v1 = volts[anode];
double v2 = volts[cnode];
draw2Leads(g);
// draw arrow thingy
setPowerColor(g, true);
setVoltageColor(g, v1);
g.fillPolygon(poly);
// draw thing arrow is pointing to
setVoltageColor(g, v2);
drawThickLine(g, cathode[0], cathode[1]);
drawThickLine(g, lead2, gate[0]);
drawThickLine(g, gate[0], gate[1]);
curcount_a = updateDotCount(ia, curcount_a);
curcount_c = updateDotCount(ic, curcount_c);
curcount_g = updateDotCount(ig, curcount_g);
if (sim.dragElm != this) {
drawDots(g, point1, lead2, curcount_a);
drawDots(g, point2, lead2, curcount_c);
drawDots(g, gate[1], gate[0], curcount_g);
drawDots(g, gate[0], lead2, curcount_g+distance(gate[1], gate[0]));
}
drawPosts(g);
}
@Override double getCurrentIntoPoint(int xa, int ya) {
if (xa == point1.x && ya == point1.y)
return -ia;
if (xa == point2.x && ya == point2.y)
return -ic;
return -ig;
}
Point getPost(int n) {
return (n == 0) ? point1 : (n == 1) ? point2 : gate[1];
}
int getPostCount() { return 3; }
int getInternalNodeCount() { return 1; }
double getPower() {
return (volts[anode]-volts[gnode])*ia + (volts[cnode]-volts[gnode])*ic;
}
double aresistance;
void stamp() {
sim.stampNonLinear(nodes[anode]);
sim.stampNonLinear(nodes[cnode]);
sim.stampNonLinear(nodes[gnode]);
sim.stampNonLinear(nodes[inode]);
sim.stampResistor(nodes[gnode], nodes[cnode], cresistance);
diode.stamp(nodes[inode], nodes[gnode]);
}
void doStep() {
double vac = volts[anode]-volts[cnode]; // typically negative
double vag = volts[anode]-volts[gnode]; // typically positive
if (Math.abs(vac-lastvac) > .01 ||
Math.abs(vag-lastvag) > .01)
sim.converged = false;
lastvac = vac;
lastvag = vag;
diode.doStep(volts[inode]-volts[gnode]);
double icmult = 1/triggerI;
double iamult = 1/holdingI - icmult;
//System.out.println(icmult + " " + iamult);
aresistance = (-icmult*ic + ia*iamult > 1) ? .0105 : 10e5;
//System.out.println(vac + " " + vag + " " + sim.converged + " " + ic + " " + ia + " " + aresistance + " " + volts[inode] + " " + volts[gnode] + " " + volts[anode]);
sim.stampResistor(nodes[anode], nodes[inode], aresistance);
}
void getInfo(String arr[]) {
arr[0] = "SCR";
double vac = volts[anode]-volts[cnode];
double vag = volts[anode]-volts[gnode];
double vgc = volts[gnode]-volts[cnode];
arr[1] = "Ia = " + getCurrentText(ia);
arr[2] = "Ig = " + getCurrentText(ig);
arr[3] = "Vac = " + getVoltageText(vac);
arr[4] = "Vag = " + getVoltageText(vag);
arr[5] = "Vgc = " + getVoltageText(vgc);
}
void calculateCurrent() {
ic = (volts[cnode]-volts[gnode])/cresistance;
ia = (volts[anode]-volts[inode])/aresistance;
ig = -ic-ia;
}
public EditInfo getEditInfo(int n) {
// ohmString doesn't work here on linux
if (n == 0)
return new EditInfo("Trigger Current (A)", triggerI, 0, 0);
if (n == 1)
return new EditInfo("Holding Current (A)", holdingI, 0, 0);
if (n == 2)
return new EditInfo("Gate-Cathode Resistance (ohms)", cresistance, 0, 0);
return null;
}
public void setEditValue(int n, EditInfo ei) {
if (n == 0 && ei.value > 0)
triggerI = ei.value;
if (n == 1 && ei.value > 0)
holdingI = ei.value;
if (n == 2 && ei.value > 0)
cresistance = ei.value;
}
}