Files
EMARS/mars/tools/MarsBot.java
T
adolphenom 0da1c5dcca Source code of MARS Assembler
First commit of the 4.5 version (latest version available)
2014-12-21 12:49:28 +01:00

357 lines
15 KiB
Java

package mars.tools;
import mars.*;
import mars.mips.hardware.*;
import mars.venus.*;
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
import java.util.*;
/**
* Simple Demo of Mars tool capability
*/
public class MarsBot implements Observer, MarsTool
{
private static final int GRAPHIC_WIDTH = 512;
private static final int GRAPHIC_HEIGHT = 512;
private static final int ADDR_HEADING = 0xffff8010;
private static final int ADDR_LEAVETRACK = 0xffff8020;
private static final int ADDR_WHEREAREWEX = 0xffff8030;
private static final int ADDR_WHEREAREWEY = 0xffff8040;
private static final int ADDR_MOVE = 0xffff8050;
private MarsBotDisplay graphicArea;
private int MarsBotHeading = 0; // 0 --> North (up), 90 --> East (right), etc.
private boolean MarsBotLeaveTrack = false; // true --> leave track when moving, false --> do not ...
private double MarsBotXPosition = 0; // X pixel position of MarsBot
private double MarsBotYPosition = 0; // Y pixel position of MarsBot
private boolean MarsBotMoving = false; // true --> MarsBot is moving, false --> MarsBot not moving
// The begin and end points of a "track" segment are kept in neighboring pairs
// of elements of the array. arrayOfTrack[i] is the start pt, arrayOfTrack[i+1] is
// the end point of a path that should leave a track.
private final int trackPts = 256; // TBD Hardcoded. Array contains start-end points for segments in track.
private Point[] arrayOfTrack = new Point[trackPts];
private int trackIndex = 0;
// private inner class
private class BotRunnable implements Runnable
{
JPanel panel;
public BotRunnable() // constructor
{
final JFrame frame = new JFrame("Bot");
panel = new JPanel(new BorderLayout());
graphicArea = new MarsBotDisplay(GRAPHIC_WIDTH, GRAPHIC_HEIGHT);
JPanel buttonPanel = new JPanel();
JButton clearButton = new JButton("Clear");
clearButton.addActionListener(
new ActionListener()
{
public void actionPerformed(ActionEvent e)
{
graphicArea.clear();
MarsBotLeaveTrack = false; // true --> leave track when moving, false --> do not ...
MarsBotXPosition = 0; // X pixel position of MarsBot
MarsBotYPosition = 0; // Y pixel position of MarsBot
MarsBotMoving = false; // true --> MarsBot is moving, false --> MarsBot not moving
trackIndex = 0;
}
});
buttonPanel.add(clearButton);
JButton closeButton = new JButton("Close");
closeButton.addActionListener(
new ActionListener()
{
public void actionPerformed(ActionEvent e)
{
frame.setVisible(false);
}
});
buttonPanel.add(closeButton);
panel.add(graphicArea, BorderLayout.CENTER);
panel.add(buttonPanel, BorderLayout.SOUTH);
frame.getContentPane().add(panel);
frame.pack();
frame.setVisible(true);
frame.setTitle(" This is the MarsBot");
frame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE); // changed 12/12/09 DPS (was EXIT)
frame.setSize(GRAPHIC_WIDTH + 200, GRAPHIC_HEIGHT + 100); // TBD SIZE
frame.setVisible(true); // show();
} // end BotRunnable() constructor
public void run()
{
double tempAngle;
// infinite loop: move the bot according to the current directives
// (which may be to NOT move)
do
{
if (MarsBotMoving)
{
//System.out.println("BotRunnable.run: bot IS moving.");
// TBD This is an arbitrary distance for bot movement. This could just
// as easily be a random distance to simulate terrain, etc.
// adjust bot position.
// The "mathematical angle" is zero at east, 90 at north, etc.
// The "heading" is 0 at north, 90 at east, etc.
// Conversion: MathAngle = [(360 - heading) + 90] mod 360
tempAngle = ((360 - MarsBotHeading) + 90) % 360;
MarsBotXPosition += Math.cos(Math.toRadians(tempAngle)); // Math.cos parameter unit is radians
MarsBotYPosition += -Math.sin(Math.toRadians(tempAngle)); // Negate value because Y coord grows down
// Write this new information to MARS memory area
try
{
Globals.memory.setWord(ADDR_WHEREAREWEX, (int) MarsBotXPosition);
Globals.memory.setWord(ADDR_WHEREAREWEY, (int) MarsBotYPosition);
}
catch ( AddressErrorException e)
{
// TBD TBD TBD No action
}
//System.out.println(" ------- Heading is " + MarsBotHeading + ", angle is " + tempAngle);
//System.out.println(" ------- New X,Y is (" + MarsBotXPosition + "," + MarsBotYPosition + ")" );
// Whether or not we're leaving a track, write the current point to the
// current position in the array.
// -- If we are not leaving a track now, we will need the current point to
// start a future track, and that goes into the array.
// -- If we are leaving a track now, the current point may end the track,
// and that goes into the array.
arrayOfTrack[trackIndex] = new Point((int)MarsBotXPosition, (int)MarsBotYPosition);
}
else
{
// Action for if the MarsBot isn't moving
// System.out.println("BotRunnable.run: bot is not moving.");
}
// TBD Pause whether the bot is or is not moving. This gives the MIPS program
// opportunity to consider results of movement, or to make the bot move.
// ??? What is relationship of robot speed to MARS's
// execution time for a single instruction? Does the robot speed have to
// be slow enough to allow a MARS busy loop to detect the bot position
// at a specific pixel?
try
{
//System.out.println(" Hello from the bot runner");
Thread.sleep(40);
}
catch (InterruptedException exception)
{// no action
}
panel.repaint(); // show new bot position
} while (true);
} // end run method of BotRunnable class
} // end BotRunnable class
/* ------------------------------------------------------------------------- */
private class MarsBotDisplay extends JPanel
{
private int width;
private int height;
private boolean clearTheDisplay = true;
public MarsBotDisplay(int tw, int th)
{
width = tw;
height = th;
}
public void redraw()
{
repaint();
}
public void clear()
{
// clear the graphic display
clearTheDisplay = true;
//System.out.println("MarsBotDisplay.clear: called to clear the display");
repaint();
}
public void paintComponent(Graphics g)
{
long tempN;
// System.out.println("MarsBotDisplay.paintComponent: I'm painting! n is " + n);
// Recover Graphics2D
Graphics2D g2 = (Graphics2D) g;
/*
if (clearTheDisplay)
{
g2.setColor(Color.lightGray);
g2.fillRect(0, 0, width - 1, height - 1); // Clear all previous drawn information
clearTheDisplay = false;
}
*/
// Draw the track left behind, for each segment of the path
g2.setColor(Color.blue);
for (int i = 1; i <= trackIndex; i += 2) // Index grows by two (begin-end pair)
{
//System.out.print(".");
try
{
g2.drawLine((int)arrayOfTrack[i-1].getX(), (int)arrayOfTrack[i-1].getY(),
(int)arrayOfTrack[i].getX(), (int)arrayOfTrack[i].getY() );
}
catch (ArrayIndexOutOfBoundsException e)
{
// No action TBD sloppy
}
catch (NullPointerException e)
{
// No action TBD sloppy
}
}
g2.setColor(Color.black);
g2.fillRect((int) MarsBotXPosition, (int) MarsBotYPosition, 20, 20); // Draw bot at its current position
/*
g2.setColor(Color.blue);
g2.setFont(new Font(g2.getFont().getName(), g2.getFont().getStyle(), 20) ); // same font and style in larger size
g2.drawOval( width/2 - 30, // TBD Hardcoded oval size
height/2 - 30,
60,
60);
g2.drawString(" " + n, width/2, height/2);
*/
}
} // end private inner class MarsBotDisplay
/* ------------------------------------------------------------------------- */
public String getName()
{
return "Mars Bot";
}
/*
* This will set up the Bot's GUI. Invoked when Bot menu item selected.
*/
public void action()
{
BotRunnable br1 = new BotRunnable();
Thread t1 = new Thread(br1);
t1.start();
// New: DPS 27 Feb 2006. Register observer for memory subrange.
try {
Globals.memory.addObserver(this,0xffff8000,0xffff8060);
}
catch (AddressErrorException aee) {
System.out.println(aee);
}
}
/*
* This method observes MIPS program directives to modify Bot activity (that is,
* MIPS program write to MMIO) and updates instance variables to reflect that
* directive.
*/
public void update(Observable o, Object arg)
{
MemoryAccessNotice notice;
int address;
if (arg instanceof MemoryAccessNotice)
{
notice = (MemoryAccessNotice) arg;
address = notice.getAddress();
if (address < 0 && notice.getAccessType() == AccessNotice.WRITE)
{
String message = "";
if (address == ADDR_HEADING)
{
message = "MarsBot.update: got move heading value: ";
MarsBotHeading = notice.getValue();
//System.out.println(message + notice.getValue() );
}
else if (address == ADDR_LEAVETRACK)
{
message = "MarsBot.update: got leave track directive value ";
// If we HAD NOT been leaving a track, but we should NOW leave
// a track, put start point into array.
if (MarsBotLeaveTrack == false && notice.getValue() == 1)
{
MarsBotLeaveTrack = true;
arrayOfTrack[trackIndex] = new Point((int) MarsBotXPosition, (int) MarsBotYPosition);
trackIndex++; // the index of the end point
}
// If we HAD NOT been leaving a track, and get another directive
// to NOT leave a track, do nothing (nothing to do).
else if (MarsBotLeaveTrack == false && notice.getValue() == 0)
{
// NO ACTION
}
// If we HAD been leaving a track, and get another directive
// to LEAVE a track, do nothing (nothing to do).
else if (MarsBotLeaveTrack == true && notice.getValue() == 1)
{
// NO ACTION
}
// If we HAD been leaving a track, and get another directive
// to NOT leave a track, put end point into array.
else if (MarsBotLeaveTrack == true && notice.getValue() == 0)
{
MarsBotLeaveTrack = false;
arrayOfTrack[trackIndex] = new Point((int) MarsBotXPosition, (int) MarsBotYPosition);
trackIndex++; // the index of the next start point
}
//System.out.println("MarsBotDisplay.paintComponent: putting point in track array at " + trackIndex);
//System.out.println(message + notice.getValue() );
}
else if (address == ADDR_MOVE)
{
message = "MarsBot.update: got move control value: ";
if (notice.getValue() == 0) MarsBotMoving = false;
else MarsBotMoving = true;
//System.out.println(message + notice.getValue() );
}
else if (address == ADDR_WHEREAREWEX ||
address == ADDR_WHEREAREWEY)
{
// Ignore these memory writes, because the writes originated within
// this tool. This tool is being notified of the writes in the usual
// manner, but the writes are already known to this tool.
// NO ACTION
}
else
{
//message = "MarsBot.update: HEY!!! unknown address of " + Integer.toString(address) + ", value: ";
//System.out.println(message + notice.getValue() );
}
}
}
}
}