AP KS GM-POVInput.java

From Mech
Revision as of 04:26, 19 March 2009 by Kwang Sim (talk | contribs)
(diff) ← Older revision | Latest revision (diff) | Newer revision → (diff)
Jump to navigationJump to search
/**********************************************
 * POVController.java
 * Author:Greg McGlynn
 * Persistence-of-Vision Display project
 * Alexander Park, Kwang Xiong Sim, Greg McGlynn
 * ME 333 Mechatronics - Winter 2008
 * Northwestern University
 *
 *    This code uses the SimpleSerial code found at
 * http://alumni.media.mit.edu/~benres/simpleserial/
 * It lets you talk serial from a Java program on a Windows PC.
 * Java programmers may find this useful for a project.
 *
 *    This code runs on a PC and talks through a serial port to
 * the POV. This code is hacked together, ugly, and uncommented!
 * Read at your own risk!
 **********************************************/

import java.awt.*;
import java.awt.image.*;
import java.awt.event.*;
import javax.swing.event.*;
import java.io.*;

public class POVController extends MouseInputAdapter implements ActionListener, KeyListener, WindowListener
{

	public static void main(String[] args)
	{
                //initialization necessary to accept keyboard input (very long functions), not shown
		init();
		init2();
		init3();
		init4();

		new POVController().run();
	}

	InputStream serIn;
	OutputStream serOut; //we talk to the display with this

        //the image:
        boolean[][] leds = new boolean[width][height];

        //user interface stuff:
	final int px = 6;
	final int width = 193;
	final int height = 14;

	final int offX = 10;
	final int offY = 100;

	Checkbox eraseCheckbox;
	Button clearButton;
	Button refreshButton;
	Button dumpButton;
	Button invertButton;

	static int[][][] ascii = new int[255][][];

	public void run()
	{

		setupComPort();

		Frame f = new Frame("POV Display Controller");
		f.setSize(width*px+offX*2, height*px + offY + 20);
		f.setLayout(new FlowLayout());

		f.addMouseListener(this);
		f.addMouseMotionListener(this);
		f.addKeyListener(this);

                eraseCheckbox = new Checkbox("Erase?");
		f.add(eraseCheckbox);

		clearButton = new Button("Clear Display");
		clearButton.addActionListener(this);
		f.add(clearButton);

		refreshButton = new Button("Refresh (if the image isn't appearing)");
		refreshButton.addActionListener(this);
		f.add(refreshButton);

                dumpButton = new Button("Dump code");
		dumpButton.addActionListener(this);
		//f.add(dumpButton);

		invertButton = new Button("Invert pixels");
		invertButton.addActionListener(this);
		f.add(invertButton);

		f.setVisible(true);
		f.addWindowListener(this);
		f.requestFocus();

		BufferedImage im = new BufferedImage(width*px+1, height*px+1, BufferedImage.TYPE_INT_RGB);
		Graphics g = im.getGraphics();
		g.setColor(Color.white);
		g.fillRect(0, 0, width*px, height*px);
		g.setColor(Color.black);
		for(int x = 0; x <=  width*px; x += px) g.drawLine(x, 0, x, height*px);
		for(int y = 0; y <= height*px; y += px) g.drawLine(0, y,  width*px, y);

		while(true)
		{

			for(int x = 0; x < width; x += 1)
			{
				for(int y = 0; y < height; y += 1)
				{
					if(leds[x][y]) g.setColor(Color.red);
					else           g.setColor(Color.white);

					g.fillRect(x*px+2, y*px+2, px-3, px-3);
				}
			}

			f.getGraphics().drawImage(im, offX, offY, f);
			f.requestFocus();
			try { Thread.sleep(20); }
			catch(Exception e) {}
		}
	}

        void setupComPort() {
                System.out.print("PLEASE ENTER A COM PORT NUMBER: ");
                try {
                    int com = Integer.parseInt(new BufferedReader(new InputStreamReader(System.in)).readLine());
                    if(tryComPort(com)) return;
                    else System.out.println("That com port doesn't seem to work! :(");
                } catch(Exception e) {
                    e.printStackTrace();
                    System.out.println("Sorry, there was some kind of error! :(");
                }
                System.out.println("Press any key to exit...");
                try {
                    System.in.read();
                    System.in.read();
                } catch(Exception e) {}
                System.exit(0);
        }

        boolean tryComPort(int com) {
                SimpleSerial ss = new SimpleSerialNative(com /*com port!*/);
                serIn = ss.getInputStream();
		serOut = ss.getOutputStream();

		return (serIn != null && serOut != null);
        }


	int lastX, lastY;

	int ledX(int mouseX)
	{
		return (mouseX - offX)/px;
	}

	int ledY(int mouseY)
	{
		return (mouseY - offY)/px;
	}

	boolean inBounds(int x, int y)
	{
		return (x >= 0 && y >= 0 && x < width && y < height);
	}

	void set(int x, int y, boolean state)
	{
		if(inBounds(x, y)) leds[x][y] = state;
	}


	public void mousePressed(MouseEvent e)
	{
		lastX = ledX(e.getX());
		lastY = ledY(e.getY());
		boolean state = !eraseCheckbox.getState();
		set(lastX, lastY, state);
		updateColumn(lastX);
	}

	public void mouseDragged(MouseEvent e)
	{
		int newX = ledX(e.getX());
		int newY = ledY(e.getY());

		if(newX == lastX && newY == lastY) return;

		boolean state = !eraseCheckbox.getState();
		double dist = Math.sqrt((newX-lastX)*(newX-lastX) + (newY-lastY)*(newY-lastY));
		double dx = (newX - lastX)/dist/10;
		double dy = (newY - lastY)/dist/10;
		for(int i = 0; i < dist*10; i++)
		{
			int x = (int)(lastX + dx*i);
			int y = (int)(lastY + dy*i);
			set(x, y, state);
		}

		int startCol = (newX < lastX ? newX : lastX);
		int endCol   = (newX > lastX ? newX : lastX);
		for(int col = startCol; col <= endCol; col += 1)
		{
			updateColumn(col);
		}

		lastX = newX;
		lastY = newY;
	}

	void updateColumn(int x)
	{
		byte byte1 = (byte)(x >> 8);
		byte byte2 = (byte)(x & 255);
		byte byte3 = 0, byte4 = 0;

		//here we assume height = 14
		for(int y = 0; y < 7; y += 1)
		{
			if(leds[x][y]) byte4 |= (1 << y);
		}
		for(int y = 7; y < 14; y += 1)
		{
			if(leds[x][y]) byte3 |= (1 << (y-7));
		}

		try
		{
			serOut.write(byte1);
			serOut.write(byte2);
			serOut.write(byte3);
			serOut.write(byte4);
			try { Thread.sleep(5); }
			catch(Exception e) {}
		}
		catch(Exception e)
		{
			e.printStackTrace();
		}
	}

	final byte CLEAR = 0x00;

	void sendCommand(byte command)
	{
		try
		{
			serOut.write(0xff);
			serOut.write(0xff);
			serOut.write(0x00);
			serOut.write(command);
		}
		catch(Exception e)
		{
			e.printStackTrace();
		}
	}

	public void actionPerformed(ActionEvent e)
	{
		if(e.getSource() == clearButton)
		{
			for(int x = 0; x < width; x += 1)
			{
				for(int y = 0; y < height; y += 1)
				{
					leds[x][y] = false;
				}
			}
			sendCommand(CLEAR);
		}
		else if(e.getSource() == refreshButton)
		{
			for(int x = 0; x < width; x++)
			{
				updateColumn(x);
				try { Thread.sleep(5); } 
				catch(Exception ex) {}
			}
		} 
		else if(e.getSource() == dumpButton) 
		{
			try 
			{ 
				FileWriter fw = new FileWriter(new File("dump.txt"));

				for(int x = 0; x < width; x++) 
				{
					fw.write("pixels[" + x + "][1] = 0b0");
					for(int y = 6; y >= 0; y--) fw.write(leds[x][y] ? "1" : "0"); 
					fw.write(";\r\n");

					fw.write("pixels[" + x + "][0] = 0b0");
					for(int y = 13; y >= 7; y--) fw.write(leds[x][y] ? "1" : "0");
					fw.write(";\r\n");
				}

				fw.flush();
				fw.close();
			} 
			catch(Exception ex) {}
		} 
		else if(e.getSource() == invertButton) {
			for(int x = 0; x < width; x++) 
			{
				for(int y = 0; y < 14; y++) 
				{
					leds[x][y] = !leds[x][y];
				}
			}
		}
	}

	int asciiCursor = 0;
	int asciiWidth = 10, asciiHeight = 14;
	public void keyPressed(KeyEvent e) 
	{
		
		char c = e.getKeyChar();
		if(c >= ' ' && c <= '~' && asciiCursor + asciiWidth < width) 
		{
			for(int x = 0; x < asciiWidth; x++)
			{
				for(int y = 0; y < asciiHeight; y++) 
				{
					leds[asciiCursor + x][y] |= (ascii[c][y][x] == 1);
				}
				updateColumn(x);
			}

			asciiCursor += asciiWidth;
		}

		if(e.getKeyCode() == KeyEvent.VK_BACK_SPACE) 
		{
			if(asciiCursor >= asciiWidth) 
			{
				asciiCursor -= asciiWidth;
				for(int x = 0; x < asciiWidth; x++)
				{
					for(int y = 0; y < asciiHeight; y++) 
					{
						leds[asciiCursor + x][y] = false;
					}
					updateColumn(x);
				}
			}
		}
		
	}


	public void keyReleased(KeyEvent e) {}
	public void keyTyped(KeyEvent e) {}

	public void windowActivated(WindowEvent e) {}
	public void windowClosed(WindowEvent e) {}
	public void windowClosing(WindowEvent e) { System.exit(0); }
	public void windowDeactivated(WindowEvent e) {}
	public void windowDeiconified(WindowEvent e) {}
	public void windowIconified(WindowEvent e) {}
	public void windowOpened(WindowEvent e) {}
																																																	  

//...init# functions omitted (these just initialize ascii[][][])
}