Checkpoint of my Swing UI refactoring. Usable for output-only programs, but only barely.

This commit is contained in:
Seth Morabito committed 2012-05-28 22:18:35 -07:00
1 parent 5ce81ef82c
commit ed36690e9e
13 files changed
+776 -659

No files matched your search

+100 -92
View File
@@ -1,124 +1,132 @@
package com.loomcom.symon.devices;
import com.loomcom.symon.exceptions.*;
import com.loomcom.symon.util.*;
/**
* This is a simulation of the MOS 6551 ACIA, with limited
* functionality. Interrupts are not supported.
*
* <p/>
* Unlike a 16550 UART, the 6551 ACIA has only one-byte transmit and
* receive buffers. It is the programmer's responsibility to check the
* status (full or empty) for transmit and receive buffers before
* writing / reading. However, in the simulation we maintain two
* small buffers of 256 characters, since we only wake up to check for
* keyboard input and do output every 500 instructions.
* writing / reading.
*/
public class Acia extends Device {
public static final int ACIA_SIZE = 4;
public static final int BUF_LEN = 256;
public static final int ACIA_SIZE = 4;
static final int DATA_REG = 0;
static final int STAT_REG = 1;
static final int CMND_REG = 2;
static final int CTRL_REG = 3;
static final int DATA_REG = 0;
static final int STAT_REG = 1;
static final int CMND_REG = 2;
static final int CTRL_REG = 3;
/** Register addresses */
private int baseAddress;
/**
* Register addresses
*/
private int baseAddress;
/** Registers. These are ignored in the current implementation. */
private int commandRegister;
private int controlRegister;
/**
* Registers. These are ignored in the current implementation.
*/
private int commandRegister;
private int controlRegister;
/** Read/Write buffers */
private FifoRingBuffer rxBuffer = new FifoRingBuffer(BUF_LEN);
private FifoRingBuffer txBuffer = new FifoRingBuffer(BUF_LEN);
/**
* Read/Write buffers
*/
private int rxChar = 0;
private int txChar = 0;
public Acia(int address) throws MemoryRangeException {
super(address, ACIA_SIZE, "ACIA");
this.baseAddress = address;
}
private boolean rxFull = false;
private boolean txFull = false;
@Override
public int read(int address) throws MemoryAccessException {
switch (address) {
case DATA_REG:
try {
return rxRead();
} catch (FifoUnderrunException ex) {
throw new MemoryAccessException("Buffer underrun");
}
case STAT_REG:
return ((rxBuffer.isEmpty() ? 0x00 : 0x08) |
(txBuffer.isEmpty() ? 0x10 : 0x00));
case CMND_REG:
return commandRegister;
case CTRL_REG:
return controlRegister;
default:
throw new MemoryAccessException("No register.");
public Acia(int address) throws MemoryRangeException {
super(address, ACIA_SIZE, "ACIA");
this.baseAddress = address;
}
}
@Override
public void write(int address, int data) throws MemoryAccessException {
switch (address) {
case 0:
txWrite(data);
break;
case 1:
reset();
break;
case 2:
commandRegister = data;
break;
case 3:
controlRegister = data;
break;
default:
throw new MemoryAccessException("No register.");
@Override
public int read(int address) throws MemoryAccessException {
switch (address) {
case DATA_REG:
return rxRead();
case STAT_REG:
return ((rxFull ? 0x08 : 0x00) |
(txFull ? 0x00 : 0x10));
case CMND_REG:
return commandRegister;
case CTRL_REG:
return controlRegister;
default:
throw new MemoryAccessException("No register.");
}
}
}
@Override
public String toString() {
return "ACIA@" + String.format("%04X", baseAddress);
}
@Override
public void write(int address, int data) throws MemoryAccessException {
switch (address) {
case 0:
txWrite(data);
break;
case 1:
reset();
break;
case 2:
commandRegister = data;
break;
case 3:
controlRegister = data;
break;
default:
throw new MemoryAccessException("No register.");
}
}
public int rxRead() throws FifoUnderrunException {
return rxBuffer.pop();
}
@Override
public String toString() {
return "ACIA@" + String.format("%04X", baseAddress);
}
public void rxWrite(int data) {
rxBuffer.push(data);
}
public synchronized int rxRead() {
rxFull = false;
return rxChar;
}
public int txRead() throws FifoUnderrunException {
return txBuffer.pop();
}
public synchronized void rxWrite(int data) {
rxFull = true;
rxChar = data;
}
public void txWrite(int data) {
txBuffer.push(data);
}
public synchronized int txRead() {
txFull = false;
return txChar;
}
/**
* @return true if there is character data in the TX register.
*/
public boolean hasTxChar() {
return !txBuffer.isEmpty();
}
public synchronized void txWrite(int data) {
txFull = true;
txChar = data;
}
/**
* @return true if there is character data in the RX register.
*/
public boolean hasRxChar() {
return !rxBuffer.isEmpty();
}
/**
* @return true if there is character data in the TX register.
*/
public boolean hasTxChar() {
return txFull;
}
private void reset() {
txBuffer.reset();
rxBuffer.reset();
}
/**
* @return true if there is character data in the RX register.
*/
public boolean hasRxChar() {
return rxFull;
}
private synchronized void reset() {
txChar = 0;
txFull = false;
rxChar = 0;
rxFull = false;
}
}