Wednesday, April 13, 2022

13-Digital Components

The graphical symbols for digital components are drawn relative to the component location such that if the component is moved, it will be drawn relative to the new location. Each component is drawn using primitive graphical elements such as lines, rectancles, circles, and arcs. Digital component size is 60x60 pixels. The component Draw() methods are listed below.

AND Gate

// Let the AndGate draw itself called from the canvas paint event
public void Draw(Graphics gr)
{
    // Draw in input and output lines based on the logic state
    if (logicState)
        drawShape(gr, onPen);
    else
        drawShape(gr, offPen);
 
    // Draw the AND gate
    //gr.DrawRectangle(this.Pen, Pt.X + leadLength, Pt.Y + leadLength, gateSize-2*leadLength, gateSize - 2 * leadLength);
    gr.DrawLine(offPen, (int)Location.X + leadLength, (int)Location.Y + leadLength, (int)Location.X + 3 * leadLength, (int)Location.Y + leadLength);
    gr.DrawLine(offPen, (int)Location.X + leadLength, (int)Location.Y + gateSize - leadLength, (int)Location.X + 3 * leadLength, (int)Location.Y + gateSize - leadLength);
    gr.DrawLine(offPen, (int)Location.X + leadLength, (int)Location.Y + leadLength, (int)Location.X + leadLength, (int)Location.Y + gateSize - leadLength);
 
    float startAngle = -90F;
    float sweepAngle = 180.0F;
    Rectangle rect = new Rectangle((int)Location.X + leadLength, (int)Location.Y + leadLength, 40, 40);
    gr.DrawArc(offPen, rect, startAngle, sweepAngle);
}
 
private void drawShape(Graphics gr, Pen pen)
{
    // Draw input lines
    gr.DrawLine(pen, new Point((int)Location.X, (int)Location.Y + 2 * leadLength), new Point((int)Location.X + leadLength, (int)Location.Y + 2 * leadLength));
    gr.DrawLine(pen, new Point((int)Location.X, (int)Location.Y + gateSize - 2 * leadLength), new Point((int)Location.X + leadLength, (int)Location.Y + gateSize - 2 * leadLength));
 
    // Draw output line
    gr.DrawLine(pen, new Point((int)Location.X + gateSize - leadLength, (int)Location.Y + gateSize / 2), new Point((int)Location.X + gateSize, (int)Location.Y + gateSize / 2));
}

OR Gate

// Let the OrGate draw itself called from the canvas paint event
public void Draw(Graphics gr)
{
    // Draw input curve
    float startAngle = -70F;
    float sweepAngle = 135.0F;
    Rectangle rect = new Rectangle((int)Location.X - 25, (int)Location.Y + leadLength, 40, 40);
    gr.DrawArc(offPen, rect, startAngle, sweepAngle);
 
    // Draw bottom curve
    float bottomstartAngle = 0F;
    float bottomsweepAngle = 90.0F;
    Rectangle bottomrect = new Rectangle((int)Location.X - 37, (int)Location.Y + leadLength, 80, 38);
    gr.DrawArc(offPen, bottomrect, bottomstartAngle, bottomsweepAngle);
 
    // Draw top curve
    float topstartAngle = 270F;
    float topsweepAngle = 90.0F;
    Rectangle toprect = new Rectangle((int)Location.X - 37, (int)Location.Y + leadLength, 80, 38);
    gr.DrawArc(offPen, toprect, topstartAngle, topsweepAngle);
 
    // Draw in input and output lines based on the logic state
    if (logicState)
        drawShape(gr, onPen);
    else
        drawShape(gr, offPen);
}
 
private void drawShape(Graphics gr, Pen pen)
{
    // Draw input lines
    gr.DrawLine(pen, new Point((int)Location.X, (int)Location.Y + 20), new Point((int)Location.X + 10, (int)Location.Y + 20));
    gr.DrawLine(pen, new Point((int)Location.X, (int)Location.Y + 40), new Point((int)Location.X + 10, (int)Location.Y + 40));
 
    // Draw output line
    gr.DrawLine(pen, new Point((int)Location.X + 45, (int)Location.Y + 30), new Point((int)Location.X + 60, (int)Location.Y + 30));
}

NOT Gate

// Let the OrGate draw itself called from the canvas paint event
public void Draw(Graphics gr)
{
    // Draw the triangle
    gr.DrawLine(offPen, new Point((int)Location.X + 10, (int)Location.Y + 10), new Point((int)Location.X + 45, (int)Location.Y + 30));
    gr.DrawLine(offPen, new Point((int)Location.X + 10, (int)Location.Y + 50), new Point((int)Location.X + 45, (int)Location.Y + 30));
    gr.DrawLine(offPen, new Point((int)Location.X + 10, (int)Location.Y + 10), new Point((int)Location.X + 10, (int)Location.Y + 50));
 
    Rectangle rect = new Rectangle((int)Location.X + 45, (int)Location.Y + 27, 5, 5);
    gr.DrawEllipse(offPen, rect);
 
    // Draw in input and output lines based on the logic state
    if (logicState)
        drawShape(gr, onPen);
    else
        drawShape(gr, offPen);
}
 
public void drawShape(Graphics gr, Pen pen)
{
    // Draw input lines
    gr.DrawLine(pen, new Point((int)Location.X, (int)Location.Y + 20), new Point((int)Location.X + 10, (int)Location.Y + 20));
    gr.DrawLine(pen, new Point((int)Location.X, (int)Location.Y + 40), new Point((int)Location.X + 10, (int)Location.Y + 40));
 
    // Draw output line
    gr.DrawLine(pen, new Point((int)Location.X + 50, (int)Location.Y + 30), new Point((int)Location.X + 60, (int)Location.Y + 30));
}

Digital Switch

// Let the switch draw itself called from the canvas paint event
public void Draw(Graphics gr)
{
    // Draw outer Rectangle
    Rectangle rect = new Rectangle((int)Location.X + 20, (int)Location.Y + 10, 30, 20);
    gr.DrawRectangle(offPen, rect);
 
    // Draw switch based on switch on/off state
    if (switchState)
    {
        gr.DrawLine(onPen, new Point((int)Location.X + 50, (int)Location.Y + 20), new Point((int)Location.X + 60, (int)Location.Y + 20));
        rect = new Rectangle((int)Location.X + 25, (int)Location.Y + 15, 10, 10);
        gr.DrawRectangle(offPen, rect);
        rect = new Rectangle((int)Location.X + 35, (int)Location.Y + 15, 10, 10);
        gr.FillRectangle(new SolidBrush(Color.Black), rect);
    }
    else
    {
        gr.DrawLine(offPen, new Point((int)Location.X + 50, (int)Location.Y + 20), new Point((int)Location.X + 60, (int)Location.Y + 20));
        rect = new Rectangle((int)Location.X + 35, (int)Location.Y + 15, 10, 10);
        gr.DrawRectangle(offPen, rect);
        rect = new Rectangle((int)Location.X + 25, (int)Location.Y + 15, 10, 10);
        gr.FillRectangle(new SolidBrush(Color.Black), rect);
    }
 
    // Draw the output pin hot spot
    drawHotSpots(gr);
}
 
private void drawHotSpots(Graphics gr)
{
    if (this.hotSpotsVisible)
    {
        // Draw hot spot for output pin
        Rectangle rect1 = new Rectangle(
                (int)Location.X + 60 - endcap_radius, (int)Location.Y + 20 - endcap_radius,
                2 * endcap_radius, 2 * endcap_radius);
        gr.DrawRectangle(Pens.Red, rect1);     // Rectangular hot spot
    }
}

Light Emitting Diode (LED)

// Let the LED draw itself called from the canvas paint event
public void Draw(Graphics gr)
{
    // Draw outer circle
    Rectangle rect = new Rectangle((int)Location.X + 10, (int)Location.Y + 10, 20, 20);
    gr.FillEllipse(new SolidBrush(offColor), rect);
 
    // Draw inner circle = LED based on the LED state
    if (Pin[0])
    {
        gr.DrawLine(this.onPen, new Point((int)Location.X, (int)Location.Y + 20), new Point((int)Location.X + 10, (int)Location.Y + 20));
        rect = new Rectangle((int)Location.X + 12, (int)Location.Y + 12, 16, 16);
        gr.FillEllipse(this.onfillColor, rect);
    }
    else
    {
        gr.DrawLine(this.offPen, new Point((int)Location.X, (int)Location.Y + 20), new Point((int)Location.X + 10, (int)Location.Y + 20));
        rect = new Rectangle((int)Location.X + 12, (int)Location.Y + 12, 16, 16);
        gr.FillEllipse(this.offfillColor, rect);
    }
    // Draw the output pin hot spot
    drawHotSpots(gr);
}
 
private void drawHotSpots(Graphics gr)
{
    if (this.hotSpotsVisible)
    {
        // Draw hot spot for output pin
        Rectangle rect1 = new Rectangle(
                (int)Location.X - endcap_radius, (int)Location.Y + 20 - endcap_radius,
                2 * endcap_radius, 2 * endcap_radius);
        gr.DrawRectangle(Pens.Red, rect1);     // Rectangular hot spot
    }
}

Digital Switch Control

The digital switch has two logic states: on and off. The graphical symbol is changed for the two logic states. The user can right click on the switch to toggle the logic state and initiate a change of logic state for the output connected wire.

The circuit class contains a Traverse method that propagates the logic change from the switch to all connected components including output LEDs. The logic for each gate is based on the logic state of input wires. The Traverse method uses a recursive algorithm to propagate the logic states from component to component until a component does not have an output wire, ie LED.

This method is based on the book "Essential Algorithms", Rod Stephens, Wiley, 2nd Edition, Kindle Edition, Chapter 13, Traversals.

The traversal method used here to analyze the digital circuit assumes that each component contains a list of input and output wires. Each wire captures the input and output component. The algorithm starts with a digital switch which has a single output wire. The algorithm sets the logic state of the switch and it associated output wire whose colors are change in real time on the window. The algorithm then sets the next component to the output component on the wire and recursively calls itself to process the next component and its output wires. Recursion continues until a component with not output wires is found. The only component without output wires is the LED. The LED color changes for the on and off state on the window.

// Recursive algorithm to transverse the circuit and process all components
public void Traverse(Comp comp)
{
    // Traverse the circuit starting from comp and toggle logic states
    foreach (Wire wire in comp.wires)
    {
        wire.logicState = comp.Pout[0];
        wire.printWire();
        Comp tempComp = new Comp();
        tempComp = wire.outComp;
        tempComp.Pin[wire.outCompPin] = wire.logicState;
        tempComp.SetOutput();
        Traverse(tempComp); // Recursion over the wire output components
    }
}

The source code is similar to the Test Diagram project with graphical symbols for the digital components and the circuit analysis code in the Circuit.cs class. The schematicCanvas MouseDown handler checks to see if the right mouse button has been clicked on a digital switch. If it has, the traverse method is called.

The full source code for this project is available on GitHub.


No comments:

Post a Comment

34-Microwave Tools with Analysis (Series Final Post)

In this final blog post, I have integrated Y-Matrix analysis into the Microwave Tools project. This version has addition Lumped, Ideal, Micr...