Initial commit
This commit is contained in:
39
C#/DigiSim/Logic/ButtonInput.cs
Normal file
39
C#/DigiSim/Logic/ButtonInput.cs
Normal file
@@ -0,0 +1,39 @@
|
||||
using System.Windows.Controls;
|
||||
using System.Windows.Shapes;
|
||||
|
||||
namespace DigiSim.Logic {
|
||||
public class ButtonInput : Gate {
|
||||
private bool _powered;
|
||||
|
||||
protected override void InternalSetup(Canvas canvas) {
|
||||
Shape = new Ellipse();
|
||||
SetOutputs(1);
|
||||
SetInputs(0);
|
||||
CreateConnections();
|
||||
|
||||
Shape.MouseLeftButtonDown += (sender, args) => {
|
||||
if (IsAttached) return;
|
||||
_powered = true;
|
||||
Update(this);
|
||||
};
|
||||
Shape.MouseLeftButtonUp += (sender, args) => {
|
||||
if (IsAttached) return;
|
||||
_powered = false;
|
||||
Update(this);
|
||||
};
|
||||
Text = "B";
|
||||
|
||||
Instantiate();
|
||||
}
|
||||
|
||||
public override void Update(Gate source) {
|
||||
ConnectedOutputs[0].IsPowered = _powered;
|
||||
Shape.Fill = _powered ? FromHex(Window.PoweredColor) : FromHex(Window.FillColor);
|
||||
|
||||
UpdateShapes();
|
||||
UpdateConnectedGates(source);
|
||||
}
|
||||
|
||||
public ButtonInput(double x, double y) : base(x, y, 20, 20) { }
|
||||
}
|
||||
}
|
||||
308
C#/DigiSim/Logic/Gate.cs
Normal file
308
C#/DigiSim/Logic/Gate.cs
Normal file
@@ -0,0 +1,308 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Windows;
|
||||
using System.Windows.Controls;
|
||||
using System.Windows.Input;
|
||||
using System.Windows.Media;
|
||||
using System.Windows.Shapes;
|
||||
|
||||
namespace DigiSim.Logic {
|
||||
public abstract class Gate {
|
||||
private TextBlock _textBlock;
|
||||
|
||||
private MouseEventHandler _onMove;
|
||||
private MouseEventHandler _onLeave;
|
||||
private MouseButtonEventHandler _onUp;
|
||||
private MouseButtonEventHandler _onDown;
|
||||
private MouseButtonEventHandler _onDelete;
|
||||
|
||||
protected bool IsAttached;
|
||||
|
||||
public Point Position { get; private set; }
|
||||
public Size Size { get; protected set; }
|
||||
protected Shape Shape { get; set; }
|
||||
protected Tuple<Tuple<Shape, Shape>, Line>[] ConnectorLines { get; set; }
|
||||
public Ellipse[] InputShapes { get; protected set; }
|
||||
public Ellipse[] OutputShapes { get; protected set; }
|
||||
|
||||
public Wire[] ConnectedInputs { get; protected set; }
|
||||
public Wire[] ConnectedOutputs { get; protected set; }
|
||||
|
||||
protected Dictionary<bool, bool, bool> TruthTable { get; set; }
|
||||
|
||||
protected string Text { get; set; }
|
||||
|
||||
public bool IsDeleted { get; private set; }
|
||||
|
||||
protected Gate(double x, double y, double width, double height) {
|
||||
Constructor(x, y, width, height);
|
||||
}
|
||||
|
||||
protected Gate() {}
|
||||
|
||||
protected void Constructor(double x, double y, double width, double height) {
|
||||
Position = new Point(x, y);
|
||||
Size = new Size(width, height);
|
||||
_textBlock = new TextBlock()
|
||||
{TextAlignment = TextAlignment.Center, Foreground = Brushes.White, FontSize = 15, IsHitTestVisible = false };
|
||||
Setup(Window.Board);
|
||||
Shape.Fill = FromHex(Window.FillColor);
|
||||
}
|
||||
|
||||
private void Setup(Canvas canvas) {
|
||||
TruthTable = new Dictionary<bool, bool, bool>();
|
||||
_onMove = (sender, e) => {
|
||||
if (IsAttached) {
|
||||
Point mouse = Mouse.GetPosition(canvas);
|
||||
Position = new Point(
|
||||
mouse.X - Size.Width / 2,
|
||||
mouse.Y - Size.Height / 2
|
||||
);
|
||||
Update(this);
|
||||
}
|
||||
else if (Mouse.LeftButton == MouseButtonState.Pressed && e.OriginalSource.Equals(Shape) && Window.CurrentConnection == null)
|
||||
AttachToMouse();
|
||||
};
|
||||
_onUp = (s, e) => IsAttached = false;
|
||||
_onLeave = (s, e) => IsAttached = false;
|
||||
_onDown = (sender, e) => {
|
||||
if (IsAttached) return;
|
||||
|
||||
if (ConnectedOutputs != null) {
|
||||
for (int i = 0; i < ConnectedOutputs.Length; i++) {
|
||||
if (IsMouseOver(OutputShapes[i])) {
|
||||
Window.StartConnectingGates(this, i);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (ConnectedInputs != null) {
|
||||
for (int i = 0; i < ConnectedInputs.Length; i++) {
|
||||
Wire wire = ConnectedInputs[i];
|
||||
|
||||
if (IsMouseOver(InputShapes[i])) {
|
||||
wire.Delete();
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
_onDelete = (sender, e) => {
|
||||
if (e.OriginalSource.Equals(Shape))
|
||||
Window.DeleteGate(this);
|
||||
};
|
||||
|
||||
canvas.MouseMove += _onMove;
|
||||
canvas.MouseLeave += _onLeave;
|
||||
canvas.MouseUp += _onUp;
|
||||
canvas.MouseDown += _onDown;
|
||||
canvas.MouseRightButtonUp += _onDelete;
|
||||
|
||||
InternalSetup(canvas);
|
||||
|
||||
if (InputShapes != null) ConnectedInputs = Enumerable.Repeat(new Wire(), InputShapes.Length).ToArray();
|
||||
if (OutputShapes != null) ConnectedOutputs = Enumerable.Repeat(new Wire(), OutputShapes.Length).ToArray();
|
||||
|
||||
Update(this);
|
||||
}
|
||||
|
||||
public void AttachToMouse() {
|
||||
IsAttached = true;
|
||||
}
|
||||
|
||||
protected abstract void InternalSetup(Canvas canvas);
|
||||
public abstract void Update(Gate source);
|
||||
|
||||
protected void UpdateShapes() {
|
||||
Shape.Width = Size.Width;
|
||||
Shape.Height = Size.Height;
|
||||
Canvas.SetLeft(Shape, Position.X);
|
||||
Canvas.SetTop(Shape, Position.Y);
|
||||
Canvas.SetZIndex(Shape, 10);
|
||||
|
||||
double outSpace = Size.Height / OutputShapes.Length;
|
||||
for (int i = 0; i < OutputShapes.Length; i++) {
|
||||
Shape shape = OutputShapes[i];
|
||||
shape.Width = 10;
|
||||
shape.Height = 10;
|
||||
shape.Fill = ConnectedOutputs[i].IsPowered ? FromHex(Window.PoweredColor) : FromHex(Window.FillColor);
|
||||
Canvas.SetLeft(shape, Position.X + Size.Width + 5);
|
||||
Canvas.SetTop(shape, Position.Y + outSpace * i + outSpace / 2 - 5);
|
||||
Canvas.SetZIndex(shape, 2);
|
||||
}
|
||||
|
||||
double inSpace = Size.Height / InputShapes.Length;
|
||||
for (int i = 0; i < InputShapes.Length; i++) {
|
||||
Shape shape = InputShapes[i];
|
||||
shape.Width = 10;
|
||||
shape.Height = 10;
|
||||
shape.Fill = ConnectedInputs[i].IsPowered ? FromHex(Window.PoweredColor) : FromHex(Window.FillColor);
|
||||
Canvas.SetLeft(shape, Position.X - 15);
|
||||
Canvas.SetTop(shape, Position.Y + inSpace * i + inSpace / 2 - 5);
|
||||
Canvas.SetZIndex(shape, 2);
|
||||
}
|
||||
|
||||
foreach (var line in ConnectorLines) {
|
||||
Tuple<Shape, Shape> t = line.Item1;
|
||||
Point p1 = new Point(Canvas.GetLeft(t.Item1) + t.Item1.Width / 2, 0);
|
||||
Point p2 = new Point(Canvas.GetLeft(t.Item2) + t.Item2.Width / 2,
|
||||
Canvas.GetTop(t.Item2) + t.Item2.Height / 2);
|
||||
|
||||
line.Item2.Stroke = FromHex(Window.FillColor);
|
||||
line.Item2.StrokeThickness = 1;
|
||||
line.Item2.X1 = p1.X;
|
||||
line.Item2.X2 = p2.X;
|
||||
line.Item2.Y1 = p2.Y;
|
||||
line.Item2.Y2 = p2.Y;
|
||||
|
||||
Canvas.SetZIndex(line.Item2, 1);
|
||||
}
|
||||
|
||||
_textBlock.Width = Size.Width;
|
||||
_textBlock.Height = Size.Height;
|
||||
Canvas.SetLeft(_textBlock, Position.X);
|
||||
Canvas.SetTop(_textBlock, Position.Y);
|
||||
Canvas.SetZIndex(_textBlock, 11);
|
||||
_textBlock.Text = Text;
|
||||
}
|
||||
|
||||
protected void UpdateConnectedGates(Gate source) {
|
||||
if (ConnectedOutputs != null) {
|
||||
foreach (var output in ConnectedOutputs) {
|
||||
if (output != null)
|
||||
output.Update();
|
||||
else continue;
|
||||
if (output.Site2 != null) {
|
||||
if (output.Site2 != source)
|
||||
output.Site2.Update(source);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (ConnectedInputs != null) {
|
||||
foreach (var input in ConnectedInputs) {
|
||||
if (input != null)
|
||||
input.Update();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
protected void SetInputs(int count) {
|
||||
InputShapes = new Ellipse[count];
|
||||
for (int i = 0; i < count; i++) {
|
||||
InputShapes[i] = new Ellipse();
|
||||
}
|
||||
}
|
||||
protected void SetOutputs(int count) {
|
||||
OutputShapes = new Ellipse[count];
|
||||
for (int i = 0; i < count; i++) {
|
||||
OutputShapes[i] = new Ellipse();
|
||||
}
|
||||
}
|
||||
|
||||
protected void CreateConnections() {
|
||||
List<Tuple<Tuple<Shape, Shape>, Line>> connections = new List<Tuple<Tuple<Shape, Shape>, Line>>();
|
||||
foreach (var inputShape in InputShapes) {
|
||||
connections.Add(new Tuple<Tuple<Shape, Shape>, Line>(new Tuple<Shape, Shape>(Shape, inputShape), new Line()));
|
||||
}
|
||||
foreach (var outputShape in OutputShapes) {
|
||||
connections.Add(new Tuple<Tuple<Shape, Shape>, Line>(new Tuple<Shape, Shape>(Shape, outputShape), new Line()));
|
||||
}
|
||||
ConnectorLines = connections.ToArray();
|
||||
}
|
||||
|
||||
protected void Instantiate() {
|
||||
foreach (var connectorLine in ConnectorLines) {
|
||||
Window.Board.Children.Add(connectorLine.Item2);
|
||||
}
|
||||
|
||||
foreach (var inputShape in InputShapes) {
|
||||
Window.Board.Children.Add(inputShape);
|
||||
}
|
||||
|
||||
foreach (var outputShape in OutputShapes) {
|
||||
Window.Board.Children.Add(outputShape);
|
||||
}
|
||||
|
||||
Window.Board.Children.Add(Shape);
|
||||
Window.Board.Children.Add(_textBlock);
|
||||
}
|
||||
|
||||
public void Delete() {
|
||||
IsDeleted = true;
|
||||
|
||||
Window.Board.MouseMove -= _onMove;
|
||||
Window.Board.MouseLeave -= _onLeave;
|
||||
Window.Board.MouseUp -= _onUp;
|
||||
Window.Board.MouseDown -= _onDown;
|
||||
Window.Board.MouseRightButtonUp -= _onDelete;
|
||||
|
||||
Window.Board.Children.Remove(Shape);
|
||||
Window.Board.Children.Remove(_textBlock);
|
||||
|
||||
foreach (var connectorLine in ConnectorLines) {
|
||||
Window.Board.Children.Remove(connectorLine.Item2);
|
||||
}
|
||||
|
||||
foreach (var inputShape in InputShapes) {
|
||||
Window.Board.Children.Remove(inputShape);
|
||||
}
|
||||
|
||||
foreach (var outputShape in OutputShapes) {
|
||||
Window.Board.Children.Remove(outputShape);
|
||||
}
|
||||
|
||||
|
||||
foreach (var connectedInput in ConnectedInputs) {
|
||||
connectedInput.Delete();
|
||||
}
|
||||
ConnectedInputs = null;
|
||||
|
||||
foreach (var connectedOutput in ConnectedOutputs) {
|
||||
connectedOutput.Delete();
|
||||
}
|
||||
ConnectedOutputs = null;
|
||||
}
|
||||
|
||||
// STATIC UTILITIY METHODS
|
||||
|
||||
private static Rect GetBounds(Shape shape) {
|
||||
return shape.TransformToVisual(Window.Board)
|
||||
.TransformBounds(new Rect(0, 0, shape.ActualWidth, shape.ActualHeight));
|
||||
}
|
||||
|
||||
public static bool CheckBoundingIntersection(Shape shape1, Shape shape2) {
|
||||
return GetBounds(shape1).IntersectsWith(GetBounds(shape2));
|
||||
}
|
||||
|
||||
public static bool IsMouseOver(Shape shape) {
|
||||
return GetBounds(shape).Contains(Mouse.GetPosition(Window.Board));
|
||||
}
|
||||
|
||||
public static SolidColorBrush FromHex(String hex) {
|
||||
return (SolidColorBrush)new BrushConverter().ConvertFromString(hex);
|
||||
}
|
||||
}
|
||||
|
||||
public class Dictionary<TKey1,TKey2,TValue> : Dictionary<Tuple<TKey1, TKey2>, TValue>, IDictionary<Tuple<TKey1, TKey2>, TValue>
|
||||
{
|
||||
|
||||
public TValue this[TKey1 key1, TKey2 key2]
|
||||
{
|
||||
get { return base[Tuple.Create(key1, key2)]; }
|
||||
set { base[Tuple.Create(key1, key2)] = value; }
|
||||
}
|
||||
|
||||
public void Add(TKey1 key1, TKey2 key2, TValue value)
|
||||
{
|
||||
base.Add(Tuple.Create(key1, key2), value);
|
||||
}
|
||||
|
||||
public bool ContainsKey(TKey1 key1, TKey2 key2)
|
||||
{
|
||||
return base.ContainsKey(Tuple.Create(key1, key2));
|
||||
}
|
||||
}
|
||||
}
|
||||
30
C#/DigiSim/Logic/Gates/AndGate.cs
Normal file
30
C#/DigiSim/Logic/Gates/AndGate.cs
Normal file
@@ -0,0 +1,30 @@
|
||||
using System.Windows.Controls;
|
||||
using System.Windows.Shapes;
|
||||
|
||||
namespace DigiSim.Logic.Gates {
|
||||
public class AndGate : Gate {
|
||||
public AndGate(double x, double y) : base(x, y, 50, 50) { }
|
||||
protected override void InternalSetup(Canvas canvas) {
|
||||
TruthTable.Add(false, false, false);
|
||||
TruthTable.Add(false, true, false);
|
||||
TruthTable.Add(true, false, false);
|
||||
TruthTable.Add(true, true, true);
|
||||
|
||||
Shape = new Rectangle();
|
||||
SetInputs(2);
|
||||
SetOutputs(1);
|
||||
CreateConnections();
|
||||
|
||||
Text = "&";
|
||||
|
||||
Instantiate();
|
||||
}
|
||||
|
||||
public override void Update(Gate source) {
|
||||
ConnectedOutputs[0].IsPowered = TruthTable[ConnectedInputs[0].IsPowered, ConnectedInputs[1].IsPowered];
|
||||
|
||||
UpdateShapes();
|
||||
UpdateConnectedGates(source);
|
||||
}
|
||||
}
|
||||
}
|
||||
142
C#/DigiSim/Logic/Gates/CustomGate.cs
Normal file
142
C#/DigiSim/Logic/Gates/CustomGate.cs
Normal file
@@ -0,0 +1,142 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Windows;
|
||||
using System.Windows.Controls;
|
||||
using System.Windows.Shapes;
|
||||
|
||||
namespace DigiSim.Logic.Gates {
|
||||
public class CustomGate : Gate {
|
||||
public int Inputs { get; }
|
||||
public int Outputs { get; }
|
||||
public string Symbol { get; }
|
||||
public LookupTable Lookup { get; }
|
||||
|
||||
public CustomGate(double x, double y) : base(x, y, 50, 50) { }
|
||||
|
||||
private CustomGate(string symbol, LookupTable lookup) {
|
||||
Symbol = symbol;
|
||||
Lookup = lookup;
|
||||
Inputs = lookup.InputCount;
|
||||
Outputs = lookup.OutputCount;
|
||||
Constructor(0, 0, 0, 0);
|
||||
}
|
||||
|
||||
protected override void InternalSetup(Canvas canvas) {
|
||||
Shape = new Rectangle();
|
||||
int connectorCount = Math.Max(Inputs, Outputs);
|
||||
Size = new Size(50, connectorCount * 25);
|
||||
|
||||
SetInputs(Inputs);
|
||||
SetOutputs(Outputs);
|
||||
CreateConnections();
|
||||
|
||||
Text = Symbol;
|
||||
|
||||
Instantiate();
|
||||
}
|
||||
|
||||
public override void Update(Gate source) {
|
||||
bool[] snapshot = new bool[ConnectedInputs.Length];
|
||||
for (var i = 0; i < snapshot.Length; i++) {
|
||||
snapshot[i] = ConnectedInputs[i].IsPowered;
|
||||
}
|
||||
|
||||
bool[] outputs = Lookup.GetOutputs(snapshot);
|
||||
|
||||
for (var i = 0; i < ConnectedOutputs.Length; i++) {
|
||||
ConnectedOutputs[i].IsPowered = outputs[i];
|
||||
}
|
||||
|
||||
UpdateShapes();
|
||||
UpdateConnectedGates(source);
|
||||
}
|
||||
|
||||
public struct LookupTable {
|
||||
public bool[,] Inputs { get; }
|
||||
public bool[,] Outputs { get; }
|
||||
|
||||
public int InputCount { get; }
|
||||
public int OutputCount { get; }
|
||||
public int Length { get; }
|
||||
|
||||
public LookupTable(int inputCount, int outputCount, int length) {
|
||||
Inputs = new bool[length, inputCount];
|
||||
Outputs = new bool[length, outputCount];
|
||||
InputCount = inputCount;
|
||||
OutputCount = outputCount;
|
||||
Length = length;
|
||||
}
|
||||
|
||||
public bool[] GetOutputs(bool[] inputs) {
|
||||
if (inputs.Length != InputCount) throw new ArgumentOutOfRangeException(nameof(inputs));
|
||||
for (int i = 0; i < Length; i++) {
|
||||
bool found = true;
|
||||
for (int j = 0; j < InputCount; j++) {
|
||||
if (Inputs[i, j] != inputs[j]) {
|
||||
found = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (found) {
|
||||
bool[] output = new bool[OutputCount];
|
||||
for (int o = 0; o < OutputCount; o++) {
|
||||
output[o] = Outputs[i, o];
|
||||
}
|
||||
return output;
|
||||
}
|
||||
}
|
||||
|
||||
return new bool[OutputCount];
|
||||
}
|
||||
|
||||
public void SetLookup(bool[] inputs, bool[] outputs, int index) {
|
||||
if (index >= Length) throw new IndexOutOfRangeException(nameof(index));
|
||||
for (var i = 0; i < inputs.Length; i++) {
|
||||
Inputs[index, i] = inputs[i];
|
||||
}
|
||||
for (var i = 0; i < outputs.Length; i++) {
|
||||
Outputs[index, i] = outputs[i];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static LookupTable CreateLookup(Gate[] gates) {
|
||||
List<Input> inputs = new List<Input>();
|
||||
List<Output> outputs = new List<Output>();
|
||||
|
||||
foreach (var gate in gates) {
|
||||
if (gate is Input)
|
||||
inputs.Add(gate as Input);
|
||||
if (gate is Output)
|
||||
outputs.Add(gate as Output);
|
||||
}
|
||||
|
||||
int possibilities = (int) Math.Pow(2, inputs.Count);
|
||||
LookupTable lookupTable = new LookupTable(inputs.Count, outputs.Count, possibilities);
|
||||
for (var i = 0; i < possibilities; i++) {
|
||||
bool[] inputSequenze = new bool[inputs.Count];
|
||||
bool[] outputSequenze = new bool[outputs.Count];
|
||||
|
||||
char[] sequenze = Convert.ToString(i, 2).PadLeft(inputs.Count, '0').ToCharArray();
|
||||
for (var j = 0; j < sequenze.Length; j++) {
|
||||
inputSequenze[j] = sequenze[j] == '1';
|
||||
inputs[j].Powered = sequenze[j] == '1';
|
||||
inputs[j].Update(inputs[j]);
|
||||
}
|
||||
|
||||
for (var j = 0; j < outputs.Count; j++) {
|
||||
outputSequenze[j] = outputs[j].ConnectedInputs[0].IsPowered;
|
||||
}
|
||||
|
||||
lookupTable.SetLookup(inputSequenze, outputSequenze, i);
|
||||
}
|
||||
|
||||
return lookupTable;
|
||||
}
|
||||
|
||||
public static CustomGate CreateCustomGateFromBoard(Gate[] gates, string symbol) {
|
||||
return new CustomGate(symbol, CreateLookup(gates));
|
||||
}
|
||||
}
|
||||
}
|
||||
30
C#/DigiSim/Logic/Gates/NandGate.cs
Normal file
30
C#/DigiSim/Logic/Gates/NandGate.cs
Normal file
@@ -0,0 +1,30 @@
|
||||
using System.Windows.Controls;
|
||||
using System.Windows.Shapes;
|
||||
|
||||
namespace DigiSim.Logic.Gates {
|
||||
public class NandGate : Gate {
|
||||
public NandGate(double x, double y) : base(x, y, 50, 50) { }
|
||||
protected override void InternalSetup(Canvas canvas) {
|
||||
TruthTable.Add(false, false, true);
|
||||
TruthTable.Add(false, true, true);
|
||||
TruthTable.Add(true, false, true);
|
||||
TruthTable.Add(true, true, false);
|
||||
|
||||
Shape = new Rectangle();
|
||||
SetInputs(2);
|
||||
SetOutputs(1);
|
||||
CreateConnections();
|
||||
|
||||
Text = "!&";
|
||||
|
||||
Instantiate();
|
||||
}
|
||||
|
||||
public override void Update(Gate source) {
|
||||
ConnectedOutputs[0].IsPowered = TruthTable[ConnectedInputs[0].IsPowered, ConnectedInputs[1].IsPowered];
|
||||
|
||||
UpdateShapes();
|
||||
UpdateConnectedGates(source);
|
||||
}
|
||||
}
|
||||
}
|
||||
30
C#/DigiSim/Logic/Gates/NorGate.cs
Normal file
30
C#/DigiSim/Logic/Gates/NorGate.cs
Normal file
@@ -0,0 +1,30 @@
|
||||
using System.Windows.Controls;
|
||||
using System.Windows.Shapes;
|
||||
|
||||
namespace DigiSim.Logic.Gates {
|
||||
public class NorGate : Gate {
|
||||
public NorGate(double x, double y) : base(x, y, 50, 50) { }
|
||||
protected override void InternalSetup(Canvas canvas) {
|
||||
TruthTable.Add(false, false, true);
|
||||
TruthTable.Add(false, true, false);
|
||||
TruthTable.Add(true, false, false);
|
||||
TruthTable.Add(true, true, false);
|
||||
|
||||
Shape = new Rectangle();
|
||||
SetInputs(2);
|
||||
SetOutputs(1);
|
||||
CreateConnections();
|
||||
|
||||
Text = "!>1";
|
||||
|
||||
Instantiate();
|
||||
}
|
||||
|
||||
public override void Update(Gate source) {
|
||||
ConnectedOutputs[0].IsPowered = TruthTable[ConnectedInputs[0].IsPowered, ConnectedInputs[1].IsPowered];
|
||||
|
||||
UpdateShapes();
|
||||
UpdateConnectedGates(source);
|
||||
}
|
||||
}
|
||||
}
|
||||
25
C#/DigiSim/Logic/Gates/NotGate.cs
Normal file
25
C#/DigiSim/Logic/Gates/NotGate.cs
Normal file
@@ -0,0 +1,25 @@
|
||||
using System.Windows.Controls;
|
||||
using System.Windows.Shapes;
|
||||
|
||||
namespace DigiSim.Logic.Gates {
|
||||
public class NotGate : Gate {
|
||||
public NotGate(double x, double y) : base(x, y, 25, 25) { }
|
||||
protected override void InternalSetup(Canvas canvas) {
|
||||
Shape = new Rectangle();
|
||||
SetInputs(1);
|
||||
SetOutputs(1);
|
||||
CreateConnections();
|
||||
|
||||
Text = "!1";
|
||||
|
||||
Instantiate();
|
||||
}
|
||||
|
||||
public override void Update(Gate source) {
|
||||
ConnectedOutputs[0].IsPowered = !ConnectedInputs[0].IsPowered;
|
||||
|
||||
UpdateShapes();
|
||||
UpdateConnectedGates(source);
|
||||
}
|
||||
}
|
||||
}
|
||||
30
C#/DigiSim/Logic/Gates/OrGate.cs
Normal file
30
C#/DigiSim/Logic/Gates/OrGate.cs
Normal file
@@ -0,0 +1,30 @@
|
||||
using System.Windows.Controls;
|
||||
using System.Windows.Shapes;
|
||||
|
||||
namespace DigiSim.Logic.Gates {
|
||||
public class OrGate : Gate {
|
||||
public OrGate(double x, double y) : base(x, y, 50, 50) { }
|
||||
protected override void InternalSetup(Canvas canvas) {
|
||||
TruthTable.Add(false, false, false);
|
||||
TruthTable.Add(false, true, true);
|
||||
TruthTable.Add(true, false, true);
|
||||
TruthTable.Add(true, true, true);
|
||||
|
||||
Shape = new Rectangle();
|
||||
SetInputs(2);
|
||||
SetOutputs(1);
|
||||
CreateConnections();
|
||||
|
||||
Text = ">1";
|
||||
|
||||
Instantiate();
|
||||
}
|
||||
|
||||
public override void Update(Gate source) {
|
||||
ConnectedOutputs[0].IsPowered = TruthTable[ConnectedInputs[0].IsPowered, ConnectedInputs[1].IsPowered];
|
||||
|
||||
UpdateShapes();
|
||||
UpdateConnectedGates(source);
|
||||
}
|
||||
}
|
||||
}
|
||||
30
C#/DigiSim/Logic/Gates/XnorGate.cs
Normal file
30
C#/DigiSim/Logic/Gates/XnorGate.cs
Normal file
@@ -0,0 +1,30 @@
|
||||
using System.Windows.Controls;
|
||||
using System.Windows.Shapes;
|
||||
|
||||
namespace DigiSim.Logic.Gates {
|
||||
public class XnorGate : Gate {
|
||||
public XnorGate(double x, double y) : base(x, y, 50, 50) { }
|
||||
protected override void InternalSetup(Canvas canvas) {
|
||||
TruthTable.Add(false, false, true);
|
||||
TruthTable.Add(false, true, false);
|
||||
TruthTable.Add(true, false, false);
|
||||
TruthTable.Add(true, true, true);
|
||||
|
||||
Shape = new Rectangle();
|
||||
SetInputs(2);
|
||||
SetOutputs(1);
|
||||
CreateConnections();
|
||||
|
||||
Text = "!=1";
|
||||
|
||||
Instantiate();
|
||||
}
|
||||
|
||||
public override void Update(Gate source) {
|
||||
ConnectedOutputs[0].IsPowered = TruthTable[ConnectedInputs[0].IsPowered, ConnectedInputs[1].IsPowered];
|
||||
|
||||
UpdateShapes();
|
||||
UpdateConnectedGates(source);
|
||||
}
|
||||
}
|
||||
}
|
||||
30
C#/DigiSim/Logic/Gates/XorGate.cs
Normal file
30
C#/DigiSim/Logic/Gates/XorGate.cs
Normal file
@@ -0,0 +1,30 @@
|
||||
using System.Windows.Controls;
|
||||
using System.Windows.Shapes;
|
||||
|
||||
namespace DigiSim.Logic.Gates {
|
||||
public class XorGate : Gate {
|
||||
public XorGate(double x, double y) : base(x, y, 50, 50) { }
|
||||
protected override void InternalSetup(Canvas canvas) {
|
||||
TruthTable.Add(false, false, false);
|
||||
TruthTable.Add(false, true, true);
|
||||
TruthTable.Add(true, false, true);
|
||||
TruthTable.Add(true, true, false);
|
||||
|
||||
Shape = new Rectangle();
|
||||
SetInputs(2);
|
||||
SetOutputs(1);
|
||||
CreateConnections();
|
||||
|
||||
Text = "=1";
|
||||
|
||||
Instantiate();
|
||||
}
|
||||
|
||||
public override void Update(Gate source) {
|
||||
ConnectedOutputs[0].IsPowered = TruthTable[ConnectedInputs[0].IsPowered, ConnectedInputs[1].IsPowered];
|
||||
|
||||
UpdateShapes();
|
||||
UpdateConnectedGates(source);
|
||||
}
|
||||
}
|
||||
}
|
||||
34
C#/DigiSim/Logic/Input.cs
Normal file
34
C#/DigiSim/Logic/Input.cs
Normal file
@@ -0,0 +1,34 @@
|
||||
using System.Windows.Controls;
|
||||
using System.Windows.Shapes;
|
||||
|
||||
namespace DigiSim.Logic {
|
||||
public class Input : Gate {
|
||||
public bool Powered;
|
||||
|
||||
protected override void InternalSetup(Canvas canvas) {
|
||||
Shape = new Ellipse();
|
||||
SetOutputs(1);
|
||||
SetInputs(0);
|
||||
CreateConnections();
|
||||
|
||||
Shape.MouseLeftButtonUp += (sender, args) => {
|
||||
if (IsAttached) return;
|
||||
Powered = !Powered;
|
||||
Update(this);
|
||||
};
|
||||
Text = "I";
|
||||
|
||||
Instantiate();
|
||||
}
|
||||
|
||||
public override void Update(Gate source) {
|
||||
ConnectedOutputs[0].IsPowered = Powered;
|
||||
Shape.Fill = Powered ? FromHex(Window.PoweredColor) : FromHex(Window.FillColor);
|
||||
|
||||
UpdateShapes();
|
||||
UpdateConnectedGates(source);
|
||||
}
|
||||
|
||||
public Input(double x, double y) : base(x, y, 20, 20) { }
|
||||
}
|
||||
}
|
||||
26
C#/DigiSim/Logic/Output.cs
Normal file
26
C#/DigiSim/Logic/Output.cs
Normal file
@@ -0,0 +1,26 @@
|
||||
using System.Windows.Controls;
|
||||
using System.Windows.Shapes;
|
||||
|
||||
namespace DigiSim.Logic {
|
||||
public class Output : Gate {
|
||||
public Output(double x, double y) : base(x, y, 20, 20) { }
|
||||
|
||||
protected override void InternalSetup(Canvas canvas) {
|
||||
Shape = new Ellipse();
|
||||
SetInputs(1);
|
||||
SetOutputs(0);
|
||||
CreateConnections();
|
||||
|
||||
Text = "O";
|
||||
|
||||
Instantiate();
|
||||
}
|
||||
|
||||
public override void Update(Gate source) {
|
||||
Shape.Fill = ConnectedInputs[0].IsPowered ? FromHex(Window.PoweredColor) : FromHex(Window.FillColor);
|
||||
|
||||
UpdateShapes();
|
||||
UpdateConnectedGates(source);
|
||||
}
|
||||
}
|
||||
}
|
||||
27
C#/DigiSim/Logic/Splitter.cs
Normal file
27
C#/DigiSim/Logic/Splitter.cs
Normal file
@@ -0,0 +1,27 @@
|
||||
using System.Windows.Controls;
|
||||
using System.Windows.Shapes;
|
||||
|
||||
namespace DigiSim.Logic {
|
||||
public class Splitter : Gate {
|
||||
public Splitter(double x, double y) : base(x, y, 25, 25) { }
|
||||
protected override void InternalSetup(Canvas canvas) {
|
||||
Shape = new Rectangle();
|
||||
SetOutputs(2);
|
||||
SetInputs(1);
|
||||
CreateConnections();
|
||||
|
||||
Text = "S";
|
||||
|
||||
Instantiate();
|
||||
}
|
||||
|
||||
public override void Update(Gate source) {
|
||||
bool input = ConnectedInputs[0].IsPowered;
|
||||
ConnectedOutputs[0].IsPowered = input;
|
||||
ConnectedOutputs[1].IsPowered = input;
|
||||
|
||||
UpdateShapes();
|
||||
UpdateConnectedGates(source);
|
||||
}
|
||||
}
|
||||
}
|
||||
74
C#/DigiSim/Logic/Wire.cs
Normal file
74
C#/DigiSim/Logic/Wire.cs
Normal file
@@ -0,0 +1,74 @@
|
||||
using System;
|
||||
using System.Windows;
|
||||
using System.Windows.Controls;
|
||||
using System.Windows.Media;
|
||||
using System.Windows.Shapes;
|
||||
|
||||
namespace DigiSim.Logic {
|
||||
public class Wire {
|
||||
public Gate Site1 { get; set; }
|
||||
public Gate Site2 { get; set; }
|
||||
|
||||
public int OutputIndex { get; set; }
|
||||
public int InputIndex { get; set; }
|
||||
|
||||
public bool IsPowered { get; set; }
|
||||
|
||||
public Line Connection { get; }
|
||||
|
||||
public Wire() {
|
||||
Connection = new Line();
|
||||
Window.Board.Children.Add(Connection);
|
||||
}
|
||||
|
||||
public void Update() {
|
||||
if (Site1 == null || Site2 == null) return;
|
||||
|
||||
Shape site1 = Site1.OutputShapes[OutputIndex];
|
||||
Shape site2 = Site2.InputShapes[InputIndex];
|
||||
|
||||
Point p1 = new Point(Canvas.GetLeft(site1) + site1.Width / 2,
|
||||
Canvas.GetTop(site1) + site1.Height / 2);
|
||||
Point p2 = new Point(Canvas.GetLeft(site2) + site2.Width / 2,
|
||||
Canvas.GetTop(site2) + site2.Height / 2);
|
||||
|
||||
Connection.Stroke = IsPowered ? Gate.FromHex(Window.PoweredColor) : Gate.FromHex(Window.FillColor);
|
||||
Connection.StrokeThickness = 1;
|
||||
Connection.X1 = p1.X;
|
||||
Connection.X2 = p2.X;
|
||||
Connection.Y1 = p1.Y;
|
||||
Connection.Y2 = p2.Y;
|
||||
}
|
||||
|
||||
public void ConnectShapeToPoint(Shape shape, Point point) {
|
||||
|
||||
Point p1 = new Point(Canvas.GetLeft(shape) + shape.Width / 2,
|
||||
Canvas.GetTop(shape) + shape.Height / 2);
|
||||
|
||||
Connection.Stroke = Gate.FromHex(Window.FillColor);
|
||||
Connection.StrokeThickness = 1;
|
||||
Connection.X1 = p1.X;
|
||||
Connection.X2 = point.X;
|
||||
Connection.Y1 = p1.Y;
|
||||
Connection.Y2 = point.Y;
|
||||
}
|
||||
|
||||
public void Delete() {
|
||||
Window.Board.Children.Remove(Connection);
|
||||
|
||||
if (Site1 != null) {
|
||||
if (!Site1.IsDeleted) {
|
||||
Site1.ConnectedOutputs[OutputIndex] = new Wire();
|
||||
Site1.Update(Site1);
|
||||
}
|
||||
}
|
||||
|
||||
if (Site2 != null) {
|
||||
if (!Site2.IsDeleted) {
|
||||
Site2.ConnectedInputs[InputIndex] = new Wire();
|
||||
Site2.Update(Site2);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user