And.pde 0000644 0001750 0000144 00000000563 12060657220 010741 0 ustar ben users public class And extends Gate {
public And(int x, int y) {
super(x, y);
name = "And";
}
protected boolean findState(int index) {
return input[0].get() && input[1].get();
}
public void draw() {
setPen();
tline(-1, -1, 0, -1);
tarc(0, 0, 1, 1, -PI/2, PI/2);
tline(-1, 1, 0, 1);
tline(-1, -1, -1, 1);
drawHotspots();
}
}
Clock.pde 0000644 0001750 0000144 00000000060 12060657220 011262 0 ustar ben users /*
public class Clock extends Input {
}
*/
Gate.pde 0000644 0001750 0000144 00000002706 12060657220 011120 0 ustar ben users /*A Gate is any sort of a logic gate. A few more functions are defined.
* The Gate constructor defines a gate with two inputs and a single output.
*/
public abstract class Gate extends Object {
//Delay is usually -1. When inputs change, delay counts
//down from propTime to 0, then outputs change.
int delay = 0;
/**The constructor must declare how many inputs there are, and
* manages whatever else comes up.
*/
public Gate(int x, int y) {
super(x, y);
output = new Output[1];
output[0] = new Output(this, .5, 0);
input = new Input[2];
input[0] = new Input(this, -.5, -.25);
input[1] = new Input(this, -.5, .25);
}
//Assert outputs one propagation delay after inputs change.
public void tick() {
for (int i = 0; i < output.length; i++) {
//Emulate propagation delay
if ((findState(i) != output[i].get()) && (delay == -1)) delay = propTime();
//Switch outputs after the timer runs up.
if (delay == 0) {
output[i].set(findState(i));
}
}
if (delay >= 0) delay--;
}
/**Returns the propagation delay time of a gate.*/
protected int propTime() {
return 10;
}
protected boolean findState() {
return findState(0);
}
/**Returns the nth output value,
* based only on inputs (ignoring delays & clock shenanigans)
*/
protected abstract boolean findState(int index);
protected void setPen() {
super.setPen();
stroke(GATE);
}
}
Hotspot.pde 0000644 0001750 0000144 00000007543 12060716037 011706 0 ustar ben users /**A hotspot associates Objects with each other. , both visually and programatically.
* They come in two flavors: Input and Output. They're connected to inputs and
* outputs of Objects, respectively.
* respectively.
*
* Usage:
* An Object has any number of inputs and outputs. Those are represented using
* Input and Output Hotspots.
* Inputs and Outputs link to each other. (Input-Input & Output-Output links don't make sense)
*
* An Input links to one or fewer Outputs, but an Output can be forked to link to any number of inputs.
*
* Linked Hotspots store a common circuit state. Inputs can check the current state;
* outputs can check and set the state.
*
* Gates connected to the Hotspots will change and check their states as the circuit runs.
*
*/
public abstract class Hotspot extends Object {
float dx, dy;
boolean invert = false;
Object parent;
color DISCONNECTED = color(0, 0, 0);
/**Hotspot constructor
* @param dx The X offset between the Object and the Hotspot
* @param dy The y offset between the Object and the Hotspot
*/
public Hotspot(Object obj, float dx, float dy) {
super(dx, dy);
name = "Hotspot";
this.parent = obj;
}
public void setPen() {
super.setPen();
if (invert) {
stroke(GATE);
fill(255);
}
else {
noStroke();
noFill();
}
if (!attached()) fill(DISCONNECTED);
}
public void draw() {
setPen();
float rad = 2*HOTSPOT_RADIUS_PER_GATE_SIZE * parent.getSize();
if (parent instanceof Wire) rad = 4;
ellipse(getX(), getY(), rad, rad);
}
//
//Distance functions.
//
public float distance(int ox, int oy) {
return dist(ox, oy, parent.getX()+x*parent.getSize(), parent.getY()+y*parent.getSize());
}
/**Whether this hotspot is in the grab radius of the specified x, y position
* @param x An x-coordinate
* @param y A y-coordinate
* @return Whether the distance from (x, y) to this is less than GRAB_RADIUS
*/
public boolean grab(int ox, int oy) {
return HOTSPOT_GRAB_RADIUS < distance(ox, oy);
}
//
//Association functions
//
/**Called whenever a Hotspot is moved.
* Check that all attached Hotspots are still in range, and attach any
* that've come into range.
*/
public abstract void associate();
public abstract void attach(Hotspot hot);
public abstract void detach(Hotspot hot);
public abstract boolean attached(Hotspot hot);
public abstract boolean attached();
/**Removes the Hotspot from the canvas.*/
public abstract void remove();
/**Gets the current state of the Hotspot.
* @return The Hotspot's state.
*/
public abstract boolean get();
public Object getParent() {
return parent;
}
public void setX(float x) {
this.x = x;
associate();
}
public void setY(float y) {
this.y = y;
associate();
}
public float getRealX() {
return x;
}
public float getRealY() {
return y;
}
public float getX() {
return parent.getX() + parent.getSize()*x;
}
public float getY() {
return parent.getY() + parent.getSize()*y;
}
//Override default behavior of erasing on middle click. Hotspots should never be erased on click.
protected void pressed() {
}
//Override default behavior of dragging. Hotspots are attached to gates, and should only be moved by their parent gate.
protected void dragged() {
}
protected void released() {
if (dist(mouseX, mouseY, getX(), getY()) <
parent.getSize() * 2 * HOTSPOT_RADIUS_PER_GATE_SIZE) negate();
}
public void negate() {
//Wires can't be inverted.
if (getParent() instanceof Wire) return;
invert = !invert;
dirty = true;
}
public String toString() {
return name + " at " + coord() + " attached to " + parent;
}
public String shortString() {
return name + " at " + coord() + "("+parent+")";
}
}
Input.pde 0000644 0001750 0000144 00000004543 12060657220 011340 0 ustar ben users /**Input hotspots provide inputs to gates. They associate with only a single
* Output Hotspot, and cannot be set directly.*/
public class Input extends Hotspot {
Output partner;
public Input(Object obj, float dx, float dy) {
super(obj, dx, dy);
name = "Input";
DISCONNECTED = color(255, 125, 226);
inputs.add(this);
}
public void tick() {
};
/**Adds a line between inputs and outputs to the circles drawn in the superclass.*/
public void draw() {
setPen();
//Draw lines.
if (attached() && partner.get()) stroke(TRUE);
else stroke(FALSE);
if (partner != null) line(getX(), getY(), partner.getX(), partner.getY());
//Draw bubbles.
super.draw();
}
public void associate() {
//If this input's output moves out of range, dissociate.
if (attached() && (dist(partner.getX(), partner.getY(),
getX(), getY()) > HOTSPOT_GRAB_RADIUS)) {
detach();
}
//If dissociated, search for a new partner.
if (!attached()) {
for (Output output : outputs) {
if (dist(output.getX(), output.getY(),
getX(), getY()) < HOTSPOT_GRAB_RADIUS) {
attach(output);
break;
}
}
}
}
public void attach(Hotspot hot) {
if (hot.getParent() == getParent()) return;
if (hot instanceof Output) partner = (Output) hot;
if (!hot.attached(this)) hot.attach(this);
}
public void detach(Hotspot hot) {
if (hot == partner) partner = null;
if (hot.attached(this)) hot.detach(this);
}
public void detach() {
if (partner != null && partner.attached(this)) partner.detach(this);
partner = null;
}
public boolean attached(Hotspot hot) {
return (partner == hot);
}
public boolean attached() {
return (partner != null);
}
public void remove() {
things.remove(this);
inputs.remove(this);
detach();
}
public boolean get() {
//Not technically correct: if a gate is left floating, the input is indeterminate.
//I'm emulating a pull-down resistor to make simulation work.
boolean val;
if (partner == null) val = false;
else val = partner.get();
if (invert) return !val;
else return val;
}
public String toString() {
if (partner == null) return super.toString() + "\n" + " Attached to: null";
return super.toString() + "\n" + " Attached to: " + partner.shortString();
}
}
Junction.pde 0000644 0001750 0000144 00000000001 12060705603 012012 0 ustar ben users
Logic2.pde 0000644 0001750 0000144 00000010067 12060716054 011357 0 ustar ben users import java.util.*;
//Main code of LogicSim II
/*
Changelog
1: Initial release
2: Fixed wire association problems
Added colors to jumper wires
Limited sensitivity of UserInputs to just over the input
Added inversion ability to Hotspots.
3: Added grid snapping
Added OSD & helptext
*/
//Whether a Object is selected.
boolean
dirty = true,
drawGrid = false;
PGraphics gridCanvas;
PFont font;
OSD help;
Object active = null; //The currently selected object.
//Inputs and outputs. Used to figure out associations.
List inputs = new LinkedList();
List