Checkpoint of my Swing UI refactoring. Usable for output-only programs, but only barely.
This commit is contained in:
1 parent
5ce81ef82c
commit
ed36690e9e
13 files changed
+776
-659
No files matched your search
@@ -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;
|
||||
}
|
||||
|
||||
}
|
||||
Reference in new issue
Block a user