Files
EMARS/mars/tools/DigitalLabSim.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

356 lines
13 KiB
Java

package mars.tools;
import java.awt.*;
import java.awt.event.*;
import java.util.*;
import javax.swing.*;
import javax.swing.Timer;
import mars.Globals;
import mars.mips.hardware.AddressErrorException;
import mars.mips.hardware.Coprocessor0;
import mars.mips.hardware.Memory;
import mars.mips.hardware.MemoryAccessNotice;
import mars.simulator.Exceptions;
@SuppressWarnings("serial")
/* Add these two lines in exceptions.java file
* public static final int EXTERNAL_INTERRUPT_TIMER = 0x00000100; //Add for digital Lab Sim
* public static final int EXTERNAL_INTERRUPT_HEXA_KEYBOARD = 0x00000200;// Add for digital Lab Sim
*/
/*
* Didier Teifreto LIFC Université de franche-Comté www.lifc.univ-fcomte.fr/~teifreto
* didier.teifreto@univ-fcomte.fr
*/
public class DigitalLabSim extends AbstractMarsToolAndApplication {
private static String heading = "Digital Lab Sim";
private static String version = " Version 1.0 (Didier Teifreto)";
private static final int IN_ADRESS_DISPLAY_1=Memory.memoryMapBaseAddress+0x10;
private static final int IN_ADRESS_DISPLAY_2=Memory.memoryMapBaseAddress+0x11;
private static final int IN_ADRESS_HEXA_KEYBOARD=Memory.memoryMapBaseAddress+0x12;
private static final int IN_ADRESS_COUNTER=Memory.memoryMapBaseAddress+0x13;
private static final int OUT_ADRESS_HEXA_KEYBOARD=Memory.memoryMapBaseAddress+0x14;
public static final int EXTERNAL_INTERRUPT_TIMER = 0x00000100; //Add for digital Lab Sim
public static final int EXTERNAL_INTERRUPT_HEXA_KEYBOARD = 0x00000200;// Add for digital Lab Sim
// GUI Interface.
private static JPanel panelTools;
// Seven Segment display
private SevenSegmentPanel sevenSegPanel;
// Keyboard
private static int KeyBoardValueButtonClick=-1; // -1 no button click
private HexaKeyboard hexaKeyPanel;
private static boolean KeyboardInterruptOnOff=false;
// Counter
private static int CounterValueMax=30;
private static int CounterValue=CounterValueMax;
private static boolean CounterInterruptOnOff=false;
private static OneSecondCounter SecondCounter;
public DigitalLabSim(String title, String heading) {
super(title,heading);
}
public DigitalLabSim() {
super (heading+", "+version, heading);
}
public static void main(String[] args) {
new DigitalLabSim(heading+", "+version,heading).go();
}
public String getName() {
return "Digital Lab Sim";
}
protected void addAsObserver(){
addAsObserver(IN_ADRESS_DISPLAY_1, IN_ADRESS_DISPLAY_1);
addAsObserver(Memory.textBaseAddress, Memory.textLimitAddress);
}
public void update(Observable ressource, Object accessNotice){
MemoryAccessNotice notice = (MemoryAccessNotice) accessNotice;
int address=notice.getAddress();
char value=(char)notice.getValue();
if(address == IN_ADRESS_DISPLAY_1)
updateSevenSegment(1, value);
else
if (address == IN_ADRESS_DISPLAY_2)
updateSevenSegment(0, value);
else
if (address == IN_ADRESS_HEXA_KEYBOARD)
updateHexaKeyboard(value);
else
if (address == IN_ADRESS_COUNTER)
updateOneSecondCounter(value);
if (CounterInterruptOnOff)
if (CounterValue >0){
CounterValue--;
}
else{
CounterValue=CounterValueMax;
if((Coprocessor0.getValue(Coprocessor0.STATUS) & 2)==0){
mars.simulator.Simulator.externalInterruptingDevice = /*Exceptions.*/EXTERNAL_INTERRUPT_TIMER;
}
}
}
protected void reset(){
sevenSegPanel.resetSevenSegment();
hexaKeyPanel.resetHexaKeyboard();
SecondCounter.resetOneSecondCounter();
}
protected JComponent buildMainDisplayArea() {
panelTools=new JPanel(new GridLayout(1,2));
sevenSegPanel=new SevenSegmentPanel();
panelTools.add(sevenSegPanel);
hexaKeyPanel = new HexaKeyboard();
panelTools.add(hexaKeyPanel);
SecondCounter= new OneSecondCounter();
return panelTools;
}
private synchronized void updateMMIOControlAndData(int dataAddr, int dataValue) {
if (!this.isBeingUsedAsAMarsTool || (this.isBeingUsedAsAMarsTool && connectButton.isConnected())) {
synchronized (Globals.memoryAndRegistersLock) {
try {
Globals.memory.setByte(dataAddr, dataValue);
}
catch (AddressErrorException aee) {
System.out.println("Tool author specified incorrect MMIO address!"+aee);
System.exit(0);
}
}
if (Globals.getGui() != null && Globals.getGui().getMainPane().getExecutePane().getTextSegmentWindow().getCodeHighlighting() ) {
Globals.getGui().getMainPane().getExecutePane().getDataSegmentWindow().updateValues();
}
}
}
protected JComponent getHelpComponent() {
final String helpContent =
" This tool is composed of 3 parts : two seven-segment displays, an hexadecimal keyboard and counter \n"+
"Seven segment display\n"+
" Byte value at address 0xFFFF0010 : command right seven segment display \n "+
" Byte value at address 0xFFFF0011 : command left seven segment display \n "+
" Each bit of these two bytes are connected to segments (bit 0 for a segment, 1 for b segment and 7 for point \n \n"+
"Hexadecimal keyboard\n"+
" Byte value at address 0xFFFF0012 : command row number of hexadecimal keyboard (bit 0 to 3) and enable keyboard interrupt (bit 7) \n" +
" Byte value at address 0xFFFF0014 : receive row and column of the key pressed, 0 if not key pressed \n"+
" The mips program have to scan, one by one, each row (send 1,2,4,8...)"+
" and then observe if a key is pressed (that mean byte value at adresse 0xFFFF0014 is different from zero). "+
" This byte value is composed of row number (4 left bits) and column number (4 right bits)"+
" Here you'll find the code for each key : 0x11,0x21,0x41,0x81,0x12,0x22,0x42,0x82,0x14,0x24,0x44,0x84,0x18,0x28,0x48,0x88. \n"+
" For exemple key number 2 return 0x41, that mean the key is on column 3 and row 1. \n"+
" If keyboard interruption is enable, an exception is started, with cause register bit number 11 set.\n \n"+
"Counter\n"+
" Byte value at address 0xFFFF0013 : If one bit of this byte is set, the counter interruption is enable.\n"+
" If counter interruption is enable, every 30 instructions, an exception is started with cause register bit number 10.\n" +
" (contributed by Didier Teifreto, dteifreto@lifc.univ-fcomte.fr)"
;
JButton help = new JButton("Help");
help.addActionListener(
new ActionListener() {
public void actionPerformed(ActionEvent e) {
JTextArea ja = new JTextArea(helpContent);
ja.setRows(20);
ja.setColumns(60);
ja.setLineWrap(true);
ja.setWrapStyleWord(true);
JOptionPane.showMessageDialog(theWindow, new JScrollPane(ja),
"Simulating the Hexa Keyboard and Seven segment display", JOptionPane.INFORMATION_MESSAGE);
}
});
return help;
}/* ....................Seven Segment display start here................................... */
/* ...........................Seven segment display start here ..............................*/
public void updateSevenSegment(int number,char value) {
sevenSegPanel.display[number].modifyDisplay(value);
}
public class SevenSegmentDisplay extends JComponent {
public char aff;
public SevenSegmentDisplay(char aff){
this.aff=aff;
this.setPreferredSize(new Dimension(60,80));
}
public void modifyDisplay(char val){
aff=val;
this.repaint();
}
public void SwitchSegment(Graphics g,char segment){
switch(segment){
case 'a': //a segment
int[]pxa1={12,9,12};
int[]pxa2={36,39,36};
int[]pya={5,8,11};
g.fillPolygon(pxa1,pya, 3);
g.fillPolygon(pxa2,pya, 3);
g.fillRect(12,5,24,6);
break;
case 'b': //b segment
int[]pxb={37,40,43};
int[]pyb1={12,9,12};
int[]pyb2={36,39,36};
g.fillPolygon(pxb,pyb1, 3);
g.fillPolygon(pxb,pyb2, 3);
g.fillRect(37,12,6,24);
break;
case 'c': // c segment
int[]pxc={37,40,43};
int[]pyc1={44,41,44};
int[]pyc2={68,71,68};
g.fillPolygon(pxc,pyc1, 3);
g.fillPolygon(pxc,pyc2, 3);
g.fillRect(37,44,6,24);
break;
case 'd': // d segment
int[]pxd1={12,9,12};
int[]pxd2={36,39,36};
int[]pyd={69,72,75};
g.fillPolygon(pxd1,pyd, 3);
g.fillPolygon(pxd2,pyd, 3);
g.fillRect(12,69,24,6);
break;
case 'e': // e segment
int[]pxe={5,8,11};
int[]pye1={44,41,44};
int[]pye2={68,71,68};
g.fillPolygon(pxe,pye1, 3);
g.fillPolygon(pxe,pye2, 3);
g.fillRect(5,44,6,24);
break;
case 'f': // f segment
int[]pxf={5,8,11};
int[]pyf1={12,9,12};
int[]pyf2={36,39,36};
g.fillPolygon(pxf,pyf1, 3);
g.fillPolygon(pxf,pyf2, 3);
g.fillRect(5,12,6,24);
break;
case 'g': // g segment
int[]pxg1={12,9,12};
int[]pxg2={36,39,36};
int[]pyg={37,40,43};
g.fillPolygon(pxg1,pyg, 3);
g.fillPolygon(pxg2,pyg, 3);
g.fillRect(12,37,24,6);
break;
case 'h': // decimal point
g.fillOval(49,68,8,8);
break;
}
}
public void paint(Graphics g) {
char c='a';
while(c<='h'){
if ((aff & 0x1) == 1)
g.setColor(Color.RED);
else
g.setColor(Color.LIGHT_GRAY);
SwitchSegment(g,c);
aff = (char)(aff >>>1);
c++;
}
}
}
public class SevenSegmentPanel extends JPanel {
public SevenSegmentDisplay[] display;
public SevenSegmentPanel(){
int i;
FlowLayout fl= new FlowLayout();
this.setLayout(fl);
display= new SevenSegmentDisplay[2];
for (i=0;i<2;i++){
display[i]= new SevenSegmentDisplay((char)(0));
this.add(display[i]);
}
}
public void modifyDisplay(int num,char val){
display[num].modifyDisplay(val);
display[num].repaint();
}
public void resetSevenSegment() {
int i;
for (i=0;i<2;i++)
modifyDisplay(i, (char)0);
}
}
/* ...........................Seven segment display end here ..............................*/
/* ....................Hexa Keyboard start here................................... */
public void updateHexaKeyboard(char row) {
int key = KeyBoardValueButtonClick;
if ((key !=-1)&& ((1 << (key / 4))==(row & 0xF))){
updateMMIOControlAndData(OUT_ADRESS_HEXA_KEYBOARD,
(char)(1 << (key / 4)) | (1 << (4+(key%4))));
}
else{
updateMMIOControlAndData(OUT_ADRESS_HEXA_KEYBOARD, 0);
}
if ((row & 0xF0) != 0)
KeyboardInterruptOnOff = true;
else
KeyboardInterruptOnOff = false;
}
public class HexaKeyboard extends JPanel{
public JButton[] button;
public HexaKeyboard(){
int i;
GridLayout layout = new GridLayout(4,4);
this.setLayout(layout);
button = new JButton[16];
for (i=0;i<16;i++){
button[i]= new JButton(Integer.toHexString(i));
button[i].setBackground(Color.WHITE);
button[i].setMargin(new Insets(10,10,10,10));
button[i].addMouseListener(new EcouteurClick(i));
this.add(button[i]);
}
}
public void resetHexaKeyboard(){
int i;
KeyBoardValueButtonClick=-1;
for(i=0;i<16;i++){
button[i].setBackground(Color.WHITE);
}
}
public class EcouteurClick implements MouseListener{
private int buttonValue;
public EcouteurClick(int val){
buttonValue=val;
}
public void mouseEntered(MouseEvent arg0) { }
public void mouseExited(MouseEvent arg0) {}
public void mousePressed(MouseEvent arg0) {}
public void mouseReleased(MouseEvent arg0) {}
public void mouseClicked(MouseEvent arg0) {
int i;
if(KeyBoardValueButtonClick!=-1){//Button already pressed -> now realease
KeyBoardValueButtonClick = -1;
updateMMIOControlAndData(OUT_ADRESS_HEXA_KEYBOARD,0);
for(i=0;i<16;i++)
button[i].setBackground(Color.WHITE);
}
else{ // new button pressed
KeyBoardValueButtonClick = buttonValue;
button[KeyBoardValueButtonClick].setBackground(Color.GREEN);
if( KeyboardInterruptOnOff && (Coprocessor0.getValue(Coprocessor0.STATUS) & 2)==0){
mars.simulator.Simulator.externalInterruptingDevice = /*Exceptions.*/EXTERNAL_INTERRUPT_HEXA_KEYBOARD;
}
}
}
}
}
/* ....................Hexa Keyboard end here................................... */
/* ....................Timer start here................................... */
public void updateOneSecondCounter(char value) {
if (value !=0){
CounterInterruptOnOff=true;
CounterValue=CounterValueMax;
}
else{
CounterInterruptOnOff=false;
}
}
public class OneSecondCounter{
public OneSecondCounter(){
CounterInterruptOnOff=false;
}
public void resetOneSecondCounter(){
CounterInterruptOnOff=false;
CounterValue=CounterValueMax;
}
}
}