Tutorial: Drawing Basic Logic Gates with GWT

From dftwiki3
Revision as of 06:29, 5 July 2014 by Thiebaut (talk | contribs)
Jump to: navigation, search

--D. Thiebaut (talk) 18:21, 4 July 2014 (EDT)



GoogleWebKitLogo.png



GWT Tutorials



This recipe illustrates how to draw logic gates on a GWT canvas. I found remarkably little information about the geometry and of the drawing of logic gates, including the OR gate and its 3 arcs, on the Web, and decided to just create the 3 basic gates: AND, INVERTER, and OR. The NAND and NOR gates can easily be generated from the information presented here.


Setup


  • Mac OSX 10.8.5 with Java SDK 1.7
  • Eclipse Kepler
  • Google WebKit gwt-6.2.1.

Sample Output


This is what we're after, below: a way to generate simple AND, OR, and INVERTER gates on a GWT canvas.

GWTLogicGatesOnCanvas.png


Gate Geometry


The geometry for the gates is given by an IEEE document, with this main illustration, shown below, and found in Chapter 9 of this on-line reference on ASICS: http://iroi.seu.edu.cn/books/asics/ASICs.htm.

GateGeometryIEEE.gif


The Java Project


Canvas3.java


/*
 * Canvas3.java
 * D. Thiebaut
 * A simple canvas application that positions a few gates in a 800x600 canvas.
 */

package dft.client;

import com.google.gwt.canvas.client.Canvas;
import com.google.gwt.canvas.dom.client.Context2d;
import com.google.gwt.core.client.EntryPoint;
import com.google.gwt.user.client.ui.Label;
import com.google.gwt.user.client.ui.RootPanel;

/**
 * The main class for the project.  Implements an empty canvas (Context2D) on which
 * a few gates are drawn, along with 3 text labels
 */
public class Canvas3 implements EntryPoint {
    Canvas canvas;
    Context2d context;
    static final int canvasHeight = 800;
    static final int canvasWidth = 600;
     
    public void onModuleLoad() {         
        canvas = Canvas.createIfSupported();
         
        if (canvas == null) {
              RootPanel.get().add(new Label("Sorry, your browser doesn't support the HTML5 Canvas element"));
              return;
        }
         
        // standard code to size the canvas 
        canvas.setStyleName("mainCanvas");      
        canvas.setWidth(canvasWidth + "px");
        canvas.setCoordinateSpaceWidth(canvasWidth);
         
        canvas.setHeight(canvasHeight + "px");      
        canvas.setCoordinateSpaceHeight(canvasHeight);
         
        RootPanel.get().add(canvas);
        context = canvas.getContext2d();
         
        // drop a few gates on the canvas         
        for ( int x = 100; x < 300; x += 75 ) {

                // some inverters facing right
        	InverterRight inv = new InverterRight( context, x, 300 );
        	inv.draw();

                // some inverters facing down 
        	InverterDown inv2 = new InverterDown( context, 300, x );
        	inv2.draw();

                // some AND gates (facing right)
        	AndGate a = new AndGate( context, x+50, 150 );
        	a.draw();

        }
        
        // an OR gate         
        OrGate or1 = new OrGate( context, 200, 200 );
        or1.draw();
        
        // Put some labels
        TextLabel L1, L2, L3;
        L1 = new TextLabel( context, "75-75", 75, 75);
        L1.draw();
        L2 = new TextLabel( context, "195-95", 195, 95);
        L2.draw();
        L3 = new TextLabel( context, "75-195", 75, 195);
        //L3.setFont( "bold 22px sans-serif");
        L3.draw();
    }
     
}

AndGate.java


package dft.client;

import com.google.gwt.canvas.dom.client.Context2d;

public class AndGate {

	Context2d context;
	double x;
	double y;
	double andGateHeight = 30;
    double andGateLength = 40;

    double xin1, yin1, xin2, yin2, xout, yout;
    
	public AndGate( Context2d c, double xx, double yy ) {
		x = xx;
		y = yy;
		context = c;
		xin1 = x;
		xin2 = x;
		yin1 = y + andGateHeight/4;
		yin2 = y + 3*andGateHeight/4;
		xout = x + andGateLength/3 + andGateHeight/2;
		yout = y + andGateHeight/2;
	}
	
	public void draw() {        
        context.moveTo( x,  y );
        context.lineTo( x, y+andGateHeight );
        context.lineTo( x+andGateLength/3, y+andGateHeight );
        context.moveTo( x,  y );
        context.lineTo( x+andGateLength/3, y );
        context.stroke();
        
        context.moveTo( x+andGateLength/3, y );
        context.arc( x+andGateLength/3 , y+andGateHeight/2, andGateHeight/2, -Math.PI/2, Math.PI/2);
        context.stroke();
	}
	
	public void drawIO() {
		context.moveTo( xin1, yin1);
		context.arc( xin1, yin1, 2, 0, Math.PI*2 );
		context.stroke();
		
		context.moveTo( xin2, yin2);
		context.arc( xin2, yin2, 2, 0, Math.PI*2 );
		context.stroke();
		
		context.moveTo( xout, yout);
		context.arc( xout, yout, 2, 0, Math.PI*2 );
		context.stroke();
	}
}


InverterDown.java


package dft.client;

import com.google.gwt.canvas.dom.client.Context2d;

public class InverterDown {
	double x;
	double y;
	double xin, yin, xout, yout;

	Context2d context = null;
	int inverterHeight = 20;
	int inverterLength = 20;
	int inverterCircleRadius = 5;
	int calculatedCenterx = 0;
	int calculatedCentery = inverterHeight + inverterCircleRadius;

	public InverterDown(Context2d c, double xx, double yy) {
		context = c;
		x = xx;
		y = yy;

		xin = x;
		yin = y;
		yout = y + inverterLength + inverterCircleRadius * 2;
		xout = x;

	}

	public void draw() {
		context.moveTo(x, y);
		context.lineTo(x - inverterHeight / 2, y);
		context.lineTo(x, y + inverterLength);
		context.lineTo(x + inverterHeight / 2, y);
		context.lineTo(x, y);
		context.stroke();

		context.moveTo(x + calculatedCenterx + inverterCircleRadius, y
				+ calculatedCentery);
		context.arc(x + calculatedCenterx, y + calculatedCentery,
				inverterCircleRadius, 0, Math.PI * 2.0, true);
		context.stroke();

	}

	public void drawIO() {
		context.moveTo(xin, yin);
		context.arc(xin, yin, 2, 0, Math.PI * 2);
		context.stroke();

		context.moveTo(xout, yout);
		context.arc(xout, yout, 2, 0, Math.PI * 2);
		context.stroke();
	}

}

InverterRight.java


package dft.client;

import com.google.gwt.canvas.dom.client.Context2d;

public class InverterRight {
	double x;
	double y;
	double xin, yin, xout, yout;

	Context2d context = null;
	int inverterHeight = 20;
	int inverterLength = 20;
	int inverterCircleRadius = 5;
	int calculatedCenterx = inverterLength + inverterCircleRadius;
	int calculatedCentery = 0;

	public InverterRight(Context2d c, double xx, double yy) {
		context = c;
		x = xx;
		y = yy;
		xin = x;
		yin = y;
		xout = x + inverterLength + inverterCircleRadius * 2;
		yout = y;
	}

	public void draw() {
		context.moveTo(x, y);
		context.lineTo(x, y - inverterHeight / 2);
		context.lineTo(x + inverterLength, y);
		context.lineTo(x, y + inverterHeight / 2);
		context.lineTo(x, y);
		context.stroke();
		context.moveTo(x + calculatedCenterx + inverterCircleRadius, y
				+ calculatedCentery);
		context.arc(x + calculatedCenterx, y + calculatedCentery,
				inverterCircleRadius, 0, Math.PI * 2.0, true);
		context.stroke();
	}

	public void drawIO() {
		context.moveTo(xin, yin);
		context.arc(xin, yin, 2, 0, Math.PI * 2);
		context.stroke();

		context.moveTo(xout, yout);
		context.arc(xout, yout, 2, 0, Math.PI * 2);
		context.stroke();
	}
}

OrGate.java


package dft.client;

import com.google.gwt.canvas.dom.client.Context2d;

/**
 * OrGate
 * 
 * @author thiebaut
 * 
 *         Defined by geometry of IEEE pub:
 *         http://iroi.seu.edu.cn/books/asics/Book/CH09/CH09-1.gif
 */
public class OrGate {

	// various points defining the gate
	Context2d context;
	double x, x1, x2, x3, x4, x5, x6;
	double y, y1, y2, y3, y4, y5, y6;

	double radius = 26;
	double height = 26;
	double flat = 10;
	double alpha, beta;

	// inputs and output
	double xin1, yin1, xin2, yin2, xout, yout;

	public OrGate(Context2d c, double xx, double yy) {
		x = xx;
		y = yy;
		context = c;

		// compute various quantities
		alpha = Math.PI / 6;
		beta = alpha;
		y1 = y - radius / 2;
		y2 = y1;
		y3 = y;
		y4 = y2 + height;
		y5 = y4;
		y6 = y;

		x6 = x - flat - radius;
		x1 = x6 + radius * Math.sqrt(3) / 2;
		x5 = x1;
		x2 = x;
		x4 = x;
		x3 = x + radius * Math.sqrt(3) / 2;

		// I/O Pins
		xin1 = x6 + radius * 0.96592582628; // cos( PI/12 )
		yin1 = y - radius * 0.2588190451; // sin( PI/12 )

		xin2 = xin1;
		yin2 = y + radius * 0.2588190451; // sin( PI/12 )

		xout = x3;
		yout = y3;
	}

	public double getXInput1() {
		return xin1;
	}

	public double getYInput1() {
		return yin1;
	}

	public double getXInput2() {
		return xin2;
	}

	public double getYInput2() {
		return yin2;
	}

	public double getXOutput() {
		return xout;
	}

	public double getYOutput() {
		return yout;
	}

	public void draw() {

		// draw 1-2
		context.moveTo(x1, y1);
		context.lineTo(x2, y2);
		context.stroke();

		// draw 2-3
		context.moveTo(x2, y2);
		context.arc(x4, y4, radius, 3 * Math.PI / 2, Math.PI * 2 - Math.PI / 6);
		context.stroke();

		// draw 4-3
		context.moveTo(x3, y3);
		context.arc(x2, y2, radius, Math.PI / 6, Math.PI / 2);
		context.stroke();

		// Draw 4-5
		context.moveTo(x4, y4);
		context.lineTo(x5, y5);
		context.stroke();

		// Draw 1-5
		context.moveTo(x1, y1);
		context.arc(x6, y6, radius, -Math.PI / 6, Math.PI / 6);
		context.stroke();
	}
}

TextLabel.java


package dft.client;

import com.google.gwt.canvas.dom.client.Context2d;

public class TextLabel {

	Context2d context;
	String text;
	double x, y;
	String font = "bold 22px sans-serif";
	
	public TextLabel( Context2d c, String t, double xx, double yy ) {
			context = c;
			text = t;
			x = xx;
			y = yy;
			setFont( font );
	}
	
	public void setFont( String f ) {
		font = f;
	}
	
	public void draw() {
		context.setFont( font );
		context.fillText( text, x, y);
	}
}