Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 11 additions & 0 deletions src/com/lushprojects/circuitjs1/client/CirSim.java
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,17 @@ public class CirSim implements NativePreviewHandler {
int hintType = -1, hintItem1, hintItem2;
String stopMessage;

// simulation temperature in Kelvin, default 27 C (300.15K) like SPICE
static double temperature = 300.15;
// electron thermal voltage = k*T/q, recalculated when temperature changes
static double vt = 0.025865;

static void setTemperature(double tempKelvin) {
temperature = tempKelvin;
vt = 1.380649e-23 * tempKelvin / 1.602176634e-19;
DiodeModel.updateAllModels();
}

double minFrameRate = 20;
boolean developerMode;

Expand Down
17 changes: 8 additions & 9 deletions src/com/lushprojects/circuitjs1/client/Diode.java
Original file line number Diff line number Diff line change
Expand Up @@ -33,15 +33,16 @@ void setup(DiodeModel model) {
zvoltage = model.breakdownVoltage;
vscale = model.vscale;
vdcoef = model.vdcoef;

vzcoef = 1 / CirSim.vt;

// sim.console("setup " + leakage + " " + zvoltage + " " + model.emissionCoefficient + " " + vdcoef);

// critical voltage for limiting; current is vscale/sqrt(2) at
// this voltage
vcrit = vscale * Math.log(vscale/(Math.sqrt(2)*leakage));
// translated, *positive* critical voltage for limiting in Zener breakdown region;
// limitstep() uses this with translated voltages in an analogous fashion to vcrit.
vzcrit = vt * Math.log(vt/(Math.sqrt(2)*leakage));
vzcrit = CirSim.vt * Math.log(CirSim.vt/(Math.sqrt(2)*leakage));
if (zvoltage == 0)
zoffset = 0;
else {
Expand All @@ -59,8 +60,6 @@ void reset() {
lastvoltdiff = 0;
}

// Electron thermal voltage at SPICE's default temperature of 27 C (300.15 K):
static final double vt = 0.025865;
// The diode's "scale voltage", the voltage increase which will raise current by a factor of e.
double vscale;
// The multiplicative equivalent of dividing by vscale (for speed).
Expand All @@ -69,7 +68,7 @@ void reset() {
// Shockley curve, but flipped and translated. This curve removes the moderating influence
// of emcoef, replacing vscale and vdcoef with vt and vzcoef.
// vzcoef is the multiplicative equivalent of dividing by vt (for speed).
static final double vzcoef = 1 / vt;
double vzcoef;
// User-specified diode parameters for forward voltage drop and Zener voltage.
double fwdrop, zvoltage;
// The diode current's scale factor, calculated from the user-specified forward voltage drop.
Expand Down Expand Up @@ -111,17 +110,17 @@ void reset() {
vnew = -vnew - zoffset;
vold = -vold - zoffset;

if (vnew > vzcrit && Math.abs(vnew - vold) > (vt + vt)) {
if (vnew > vzcrit && Math.abs(vnew - vold) > (CirSim.vt + CirSim.vt)) {
if(vold > 0) {
arg = 1 + (vnew - vold) / vt;
arg = 1 + (vnew - vold) / CirSim.vt;
if(arg > 0) {
vnew = vold + vt * Math.log(arg);
vnew = vold + CirSim.vt * Math.log(arg);
//System.out.println(oo + " " + vnew);
} else {
vnew = vzcrit;
}
} else {
vnew = vt *Math.log(vnew/vt);
vnew = CirSim.vt *Math.log(vnew/CirSim.vt);
}
sim.converged = false;
}
Expand Down
22 changes: 15 additions & 7 deletions src/com/lushprojects/circuitjs1/client/DiodeModel.java
Original file line number Diff line number Diff line change
Expand Up @@ -28,8 +28,6 @@ public class DiodeModel implements Editable, Comparable<DiodeModel> {
boolean internal;
static final int FLAGS_SIMPLE = 1;

// Electron thermal voltage at SPICE's default temperature of 27 C (300.15 K):
static final double vt = 0.025865;
// The diode's "scale voltage", the voltage increase which will raise current by a factor of e.
double vscale;
// The multiplicative equivalent of dividing by vscale (for speed).
Expand Down Expand Up @@ -142,7 +140,7 @@ static DiodeModel getModelWithParameters(double fwdrop, double zvoltage) {
}

// create a new one, converting to new parameter values
final double vscale = emcoef * vt;
final double vscale = emcoef * CirSim.vt;
final double vdcoef = 1 / vscale;
double leakage = 1 / (Math.exp(fwdrop * vdcoef) - 1);
String name = "fwdrop=" + fwdrop;
Expand Down Expand Up @@ -170,6 +168,16 @@ static void loadInternalModel(String s) {
dm.builtIn = dm.internal = true;
}

static void updateAllModels() {
if (modelMap == null)
return;
Iterator it = modelMap.entrySet().iterator();
while (it.hasNext()) {
Map.Entry<String,DiodeModel> pair = (Map.Entry)it.next();
pair.getValue().updateModel();
}
}

static void clearDumpedFlags() {
if (modelMap == null)
return;
Expand Down Expand Up @@ -314,21 +322,21 @@ public void setEditValue(int n, EditInfo ei) {
// set emission coefficient for simple mode if we have enough data
void setEmissionCoefficient() {
if (forwardCurrent > 0 && forwardVoltage > 0)
emissionCoefficient = (forwardVoltage/Math.log(forwardCurrent/saturationCurrent+1)) / vt;
emissionCoefficient = (forwardVoltage/Math.log(forwardCurrent/saturationCurrent+1)) / CirSim.vt;

seriesResistance = 0;
}

public void setForwardVoltage() {
if (forwardCurrent == 0)
forwardCurrent = 1;
forwardVoltage = emissionCoefficient*vt * Math.log(forwardCurrent/saturationCurrent+1);
forwardVoltage = emissionCoefficient*CirSim.vt * Math.log(forwardCurrent/saturationCurrent+1);
}

void updateModel() {
vscale = emissionCoefficient * vt;
vscale = emissionCoefficient * CirSim.vt;
vdcoef = 1/vscale;
fwdrop = Math.log(1/saturationCurrent + 1) * emissionCoefficient * vt;
fwdrop = Math.log(1/saturationCurrent + 1) * emissionCoefficient * CirSim.vt;
}

String dump() {
Expand Down
15 changes: 12 additions & 3 deletions src/com/lushprojects/circuitjs1/client/EditOptions.java
Original file line number Diff line number Diff line change
Expand Up @@ -91,12 +91,14 @@ public EditInfo getEditInfo(int n) {
ei.checkbox = new Checkbox("Auto-Run DC Operating Point on Reset", app.autoDCOnReset);
return ei;
}
if (n == 15) {
if (n == 15)
return new EditInfo("Simulation Temperature (\u00b0C)", CirSim.temperature - 273.15, 0, 0);
if (n == 16) {
EditInfo ei = new EditInfo("", 0, -1, -1);
ei.checkbox = new Checkbox("Auto-Adjust Timestep", sim.adjustTimeStep);
return ei;
}
if (n == 16 && sim.adjustTimeStep)
if (n == 17 && sim.adjustTimeStep)
return new EditInfo("Minimum time step size (s)", sim.minTimeStep, 0, 0).setPositive();

// don't add new options here. they are only visible if sim.adjustTimeStemp is set, and it isn't by default.
Expand Down Expand Up @@ -194,10 +196,17 @@ public void setEditValue(int n, EditInfo ei) {
if (n == 14)
app.autoDCOnReset = ei.checkbox.getState();
if (n == 15) {
double tempK = ei.value + 273.15;
if (tempK > 0) {
CirSim.setTemperature(tempK);
app.updateModels();
}
}
if (n == 16) {
sim.adjustTimeStep = ei.checkbox.getState();
ei.newDialog = true;
}
if (n == 16)
if (n == 17 && ei.value > 0)
sim.minTimeStep = ei.value;
}

Expand Down
30 changes: 14 additions & 16 deletions src/com/lushprojects/circuitjs1/client/TransistorElm.java
Original file line number Diff line number Diff line change
Expand Up @@ -76,7 +76,7 @@ public TransistorElm(int xa, int ya, int xb, int yb, int f, StringTokenizer st)
void setup() {
model = TransistorModel.getModelWithNameOrCopy(modelName, model);
modelName = model.name; // in case we couldn't find that model
vcrit = vt * Math.log(vt/(Math.sqrt(2)*model.satCur));
vcrit = CirSim.vt * Math.log(CirSim.vt/(Math.sqrt(2)*model.satCur));
noDiagonal = true;
}
boolean nonLinear() { return true; }
Expand Down Expand Up @@ -251,24 +251,22 @@ void addRoutingObstacle(WireRouter router) {
}

static final double leakage = 1e-13; // 1e-6;
// Electron thermal voltage at SPICE's default temperature of 27 C (300.15 K):
static final double vt = 0.025865;
double vcrit;
double lastvbc, lastvbe;
double limitStep(double vnew, double vold) {
double arg;
double oo = vnew;

if (vnew > vcrit && Math.abs(vnew - vold) > (vt + vt)) {
if (vnew > vcrit && Math.abs(vnew - vold) > (CirSim.vt + CirSim.vt)) {
if(vold > 0) {
arg = 1 + (vnew - vold) / vt;
arg = 1 + (vnew - vold) / CirSim.vt;
if(arg > 0) {
vnew = vold + vt * Math.log(arg);
vnew = vold + CirSim.vt * Math.log(arg);
} else {
vnew = vcrit;
}
} else {
vnew = vt *Math.log(vnew/vt);
vnew = CirSim.vt *Math.log(vnew/CirSim.vt);
}
sim.converged = false;
//System.out.println(vnew + " " + oo + " " + vold);
Expand Down Expand Up @@ -309,7 +307,7 @@ void startIteration() {
double cje = calcJunctionCap(vjBE, model.junctionCapBE, model.junctionPotBE, model.junctionExpBE);
// Add diffusion capacitance only in forward bias (like SPICE)
if (model.transitTimeF > 0 && vjBE > 0) {
double vtn = vt * model.emissionCoeffF;
double vtn = CirSim.vt * model.emissionCoeffF;
cje += model.transitTimeF * model.satCur * Math.exp(vjBE / vtn) / vtn;
}
geqBE = 2 * cje / sim.timeStep;
Expand All @@ -321,7 +319,7 @@ void startIteration() {
double cjc = calcJunctionCap(vjBC, model.junctionCapBC, model.junctionPotBC, model.junctionExpBC);
// Add diffusion capacitance only in forward bias (like SPICE)
if (model.transitTimeR > 0 && vjBC > 0) {
cjc += model.transitTimeR * model.satCur * Math.exp(vjBC / (vt * model.emissionCoeffR)) / (vt * model.emissionCoeffR);
cjc += model.transitTimeR * model.satCur * Math.exp(vjBC / (CirSim.vt * model.emissionCoeffR)) / (CirSim.vt * model.emissionCoeffR);
}
geqBC = 2 * cjc / sim.timeStep;
if (geqBC < 1e-20) { geqBC = ceqBC = capCurBC = 0; }
Expand Down Expand Up @@ -375,16 +373,16 @@ void doStep() {
double csat=model.satCur;
double oik=model.invRollOffF;
double c2=model.BEleakCur;
double vte=model.leakBEemissionCoeff*vt;
double vte=model.leakBEemissionCoeff*CirSim.vt;
double oikr=model.invRollOffR;
double c4=model.BCleakCur;
double vtc=model.leakBCemissionCoeff*vt;
double vtc=model.leakBCemissionCoeff*CirSim.vt;

// double rbpr=model.minBaseResist;
// double rbpi=model.baseResist-rbpr;
// double xjrb=model.baseCurrentHalfResist;

double vtn=vt*model.emissionCoeffF;
double vtn=CirSim.vt*model.emissionCoeffF;
double evbe, cbe, gbe, cben, gben, evben, evbc, cbc, gbc, cbcn, gbcn, evbcn;
double qb, dqbdve, dqbdvc, q2, sqarg, arg;
if(vbe > -5*vtn){
Expand All @@ -405,7 +403,7 @@ void doStep() {
gben = -c2/vbe;
cben=gben*vbe;
}
vtn=vt*model.emissionCoeffR;
vtn=CirSim.vt*model.emissionCoeffR;
if(vbc > -5*vtn) {
evbc=Math.exp(vbc/vtn);
cbc=csat*(evbc-1)+gmin*vbc;
Expand Down Expand Up @@ -557,19 +555,19 @@ void getInfo(String arr[]) {
double cjcVal = calcJunctionCap(vbc*pnp, model.junctionCapBC, model.junctionPotBC, model.junctionExpBC);
// Add diffusion capacitance from transit time
if (model.transitTimeF > 0) {
double vtn = vt * model.emissionCoeffF;
double vtn = CirSim.vt * model.emissionCoeffF;
double gdBE = model.satCur * Math.exp(vbe*pnp / vtn) / vtn;
cjeVal += model.transitTimeF * gdBE;
}
if (model.transitTimeR > 0) {
double vtn = vt * model.emissionCoeffR;
double vtn = CirSim.vt * model.emissionCoeffR;
double gdBC = model.satCur * Math.exp(vbc*pnp / vtn) / vtn;
cjcVal += model.transitTimeR * gdBC;
}
double cTotal = cjeVal + cjcVal;
if (cTotal > 0 && ic != 0) {
// gm = Ic / Vt (transconductance at operating point)
double gmVal = Math.abs(ic) / vt;
double gmVal = Math.abs(ic) / CirSim.vt;
double ft = gmVal / (2 * Math.PI * cTotal);
arr[8] = "ft = " + getUnitText(ft, "Hz");
}
Expand Down
Loading