0da1c5dcca
First commit of the 4.5 version (latest version available)
356 lines
13 KiB
Java
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;
|
|
}
|
|
}
|
|
} |