Timing and UI enhancements.
This change introduces simulated baud rates in the ACIA. Baud rate is controlled just as in the real 6551, by writing to the ACIA's control register. Baud rates between 50 and 19,200 baud are selectable. A baud rate of 0 has special meaning, and turns off all simulated baud rate delays (on a real 6551, this means to use an external clock instead of the internal baud rate generator) A busy-wait loop between steps in the simulator control program has also been added. This uses the high-resolution 'System.nanoTime()' call to wait a specific number of nanoseconds before continuing. Symon now waits at least 1uS between clock cycles, trying to approach a real 1MHz 6502 in performance. It is far from perfect, but it's better than it was. Also refactored the status panel to use a BoxLayout, and DRY-up some of the code.
This commit is contained in:
1 parent
6c0ff5a5b2
commit
c1caf8c6b4
9 files changed
+272
-128
No files matched your search
@@ -33,12 +33,21 @@ public class Simulator implements ActionListener, Observer {
|
||||
private static final int ROM_BASE = 0xe000;
|
||||
private static final int ROM_SIZE = 0x2000; // 8 KB
|
||||
|
||||
public static final int ACIA_BASE = 0xc000;
|
||||
private static final int ACIA_BASE = 0xc000;
|
||||
|
||||
// The delay in microseconds between steps.
|
||||
private static final int DELAY_BETWEEN_STEPS_NS = 1000;
|
||||
|
||||
// Since it is very expensive to update the UI with Swing's Event Dispatch Thread, we can't afford
|
||||
// to refresh the view on every simualted clock cycle. Instead, we will only refresh the view after this
|
||||
// to refresh the view on every simulated clock cycle. Instead, we will only refresh the view after this
|
||||
// number of steps when running normally.
|
||||
private static final int MAX_STEPS_BETWEEN_UPDATES = 15000;
|
||||
//
|
||||
// Since we're simulating a 1MHz 6502 here, we have a 1 us delay between steps. Setting this to 10000
|
||||
// should give us a status update every 10 ms.
|
||||
//
|
||||
// TODO: Work around the event dispatch thread with custom painting code instead of relying on Swing.
|
||||
//
|
||||
private static final int MAX_STEPS_BETWEEN_UPDATES = 10000;
|
||||
|
||||
private final static Logger logger = Logger.getLogger(Simulator.class.getName());
|
||||
|
||||
@@ -131,13 +140,16 @@ public class Simulator implements ActionListener, Observer {
|
||||
buttonContainer.add(stepButton);
|
||||
buttonContainer.add(resetButton);
|
||||
|
||||
// Left side - console and buttons
|
||||
// Left side - console
|
||||
controlsContainer.add(console, BorderLayout.PAGE_START);
|
||||
controlsContainer.add(buttonContainer, BorderLayout.PAGE_END);
|
||||
|
||||
mainWindow.getContentPane().add(controlsContainer, BorderLayout.LINE_START);
|
||||
|
||||
// Right side - status pane
|
||||
mainWindow.getContentPane().add(statusPane, BorderLayout.LINE_END);
|
||||
|
||||
// Bottom - buttons.
|
||||
mainWindow.getContentPane().add(buttonContainer, BorderLayout.PAGE_END);
|
||||
|
||||
runStopButton.addActionListener(this);
|
||||
stepButton.addActionListener(this);
|
||||
resetButton.addActionListener(this);
|
||||
@@ -325,6 +337,8 @@ public class Simulator implements ActionListener, Observer {
|
||||
*/
|
||||
private void step() throws MemoryAccessException {
|
||||
|
||||
delayLoop();
|
||||
|
||||
cpu.step();
|
||||
|
||||
// Read from the ACIA and immediately update the console if there's
|
||||
@@ -419,6 +433,16 @@ public class Simulator implements ActionListener, Observer {
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Perform a busy-loop for DELAY_BETWEEN_STEPS_NS nanoseconds
|
||||
*/
|
||||
private void delayLoop() {
|
||||
long startTime = System.nanoTime();
|
||||
long stopTime = startTime + DELAY_BETWEEN_STEPS_NS;
|
||||
// Busy loop
|
||||
while (System.nanoTime() < stopTime) { ; }
|
||||
}
|
||||
|
||||
/**
|
||||
* The main run thread.
|
||||
*/
|
||||
|
||||
Reference in new issue
Block a user