Skip to content

Commit

Permalink
tri-state outputs on custom logic (sharpie7#300)
Browse files Browse the repository at this point in the history
  • Loading branch information
pfalstad committed Apr 15, 2019
1 parent 5c61c4b commit e06e2c0
Show file tree
Hide file tree
Showing 3 changed files with 82 additions and 0 deletions.
54 changes: 54 additions & 0 deletions src/com/lushprojects/circuitjs1/client/CustomLogicElm.java
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package com.lushprojects.circuitjs1.client;

import com.google.gwt.user.client.ui.Button;
import com.lushprojects.circuitjs1.client.ChipElm.Pin;

public class CustomLogicElm extends ChipElm {
String modelName;
Expand All @@ -9,6 +10,7 @@ public class CustomLogicElm extends ChipElm {
CustomLogicModel model;
boolean lastValues[];
boolean patternValues[];
boolean highImpedance[];
static String lastModelName = "default";

public CustomLogicElm(int xx, int yy) {
Expand Down Expand Up @@ -88,6 +90,7 @@ void setupPins() {
}
lastValues = new boolean[postCount];
patternValues = new boolean[26];
highImpedance = new boolean[postCount];
}

void fixPinName(Pin p) {
Expand All @@ -108,6 +111,54 @@ int getVoltageSourceCount() {
return outputCount;
}

// keep track of whether we have any tri-state outputs. if not, then we can simplify things quite a bit, making the simulation faster
boolean hasTriState() { return model == null ? false : model.triState; }

boolean nonLinear() { return hasTriState(); }

int getInternalNodeCount() {
// for tri-state outputs, we need an internal node to connect a voltage source to, and then connect a resistor from there to the output.
// we do this for all outputs if any of them are tri-state
return (hasTriState()) ? outputCount : 0;
}

void stamp() {
int i;
int add = (hasTriState()) ? outputCount : 0;
for (i = 0; i != getPostCount(); i++) {
Pin p = pins[i];
if (p.output) {
sim.stampVoltageSource(0, nodes[i+add], p.voltSource);
if (hasTriState()) {
sim.stampNonLinear(nodes[i+add]);
sim.stampNonLinear(nodes[i]);
}
}
}
}

void doStep() {
int i;
for (i = 0; i != getPostCount(); i++) {
Pin p = pins[i];
if (!p.output)
p.value = volts[i] > 2.5;
}
execute();
int add = (hasTriState()) ? outputCount : 0;
for (i = 0; i != getPostCount(); i++) {
Pin p = pins[i];
if (p.output) {
// connect output voltage source (to internal node if tri-state, otherwise connect directly to output)
sim.updateVoltageSource(0, nodes[i+add], p.voltSource, p.value ? 5 : 0);

// add resistor for tri-state if necessary
if (hasTriState())
sim.stampResistor(nodes[i+add], nodes[i], highImpedance[i] ? 1e8 : 1e-3);
}
}
}

void execute() {
int i;
for (i = 0; i != model.rulesLeft.size(); i++) {
Expand Down Expand Up @@ -160,8 +211,11 @@ void execute() {
String rr = model.rulesRight.get(i);
for (j = 0; j != rr.length(); j++) {
char x = rr.charAt(j);
highImpedance[j+inputCount] = false;
if (x >= 'a' && x <= 'z')
pins[j+inputCount].value = patternValues[x-'a'];
else if (x == '_')
highImpedance[j+inputCount] = true;
else
pins[j+inputCount].value = (x == '1');
}
Expand Down
3 changes: 3 additions & 0 deletions src/com/lushprojects/circuitjs1/client/CustomLogicModel.java
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ public class CustomLogicModel implements Editable {
String rules;
Vector<String> rulesLeft, rulesRight;
boolean dumped;
boolean triState;

static CustomLogicModel getModelWithName(String name) {
if (modelMap == null)
Expand Down Expand Up @@ -205,6 +206,8 @@ void parseRules() {
used[x-'a'] = true;
newRl += x;
}
String rr = s0[1];
triState = (rr.contains("_"));
rulesLeft.add(newRl);
rulesRight.add(s0[1]);
}
Expand Down
25 changes: 25 additions & 0 deletions war/customlogic.html
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,8 @@
(<tt>A</tt>, <tt>B</tt>, etc.). The <i>input</i> has to be at least as long as the number of input pins. If it's longer,
than the additional pattern characters will be matched against the output pins; this allows you to create devices with state.
</p><p>
The output pattern can also contain <tt>_</tt> to indicate a high-impedance state.
</p><p>
Examples:
</p><p>
</p><h3> 3 input NAND: </h3>
Expand Down Expand Up @@ -117,4 +119,27 @@ <h3>3-Bit Counter:</h3>
? ABC=ABC
</pre>
This counter counts up on positive transition of the Clk input. The first line handles counting up from 000, 010, 100, or 110. The second line handles counting up from 001 or 101. The next two lines handle 011 and 111. The last line ensures that the output doesn't change unless the clock makes a positive transition.
</p><h3> 3 input NAND with enable: </h3>
<p>
Inputs: <tt>A,B,C,En</tt><br>
Outputs: <tt>X</tt><br>
Definition:</p><pre>1111=0
???1=1
???0=_
</pre>
<p>
Same as the 3 input NAND above, except that the output goes into a high-impedance state if the enable pin is low.
</p><p>
</p><h3> Tri-state buffer: </h3>
<p>
Inputs: <tt>A,En</tt><br>
Outputs: <tt>X</tt><br>
Definition:</p><pre>A1=A
?0=_
</pre>
<p>
Output is the same as A if the enable bit is high, otherwise it
goes into a high-impedance state if the enable pin is low.
</p><p>
</body></html>
</body></html>

0 comments on commit e06e2c0

Please sign in to comment.