mirror of
https://github.com/sethm/symon.git
synced 2024-06-03 07:29:30 +00:00
* Add ACIA Interrupt tests.
* Fix ACIA6850 Interrupt behavior, Interrupt should be cleared on status register read. * Remove unneeded cpuAccess if statement from Acia6850 write that was preventing build completion * Fix ACIA6850 Tests so they run.
This commit is contained in:
parent
3c3aee30a7
commit
faf5d22660
|
@ -30,8 +30,8 @@ import com.loomcom.symon.exceptions.MemoryRangeException;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This is a simulation of the Motorola 6850 ACIA, with limited
|
* This is a simulation of the Motorola 6850 ACIA, with limited
|
||||||
* functionality. Interrupts are not supported.
|
* functionality.
|
||||||
* <p/>
|
*
|
||||||
* Unlike a 16550 UART, the 6850 ACIA has only one-byte transmit and
|
* Unlike a 16550 UART, the 6850 ACIA has only one-byte transmit and
|
||||||
* receive buffers. It is the programmer's responsibility to check the
|
* receive buffers. It is the programmer's responsibility to check the
|
||||||
* status (full or empty) for transmit and receive buffers before
|
* status (full or empty) for transmit and receive buffers before
|
||||||
|
@ -56,9 +56,6 @@ public class Acia6850 extends Acia {
|
||||||
public int read(int address, boolean cpuAccess) throws MemoryAccessException {
|
public int read(int address, boolean cpuAccess) throws MemoryAccessException {
|
||||||
switch (address) {
|
switch (address) {
|
||||||
case RX_REG:
|
case RX_REG:
|
||||||
if (cpuAccess) {
|
|
||||||
interrupt = false;
|
|
||||||
}
|
|
||||||
return rxRead(cpuAccess);
|
return rxRead(cpuAccess);
|
||||||
case STAT_REG:
|
case STAT_REG:
|
||||||
return statusReg(cpuAccess);
|
return statusReg(cpuAccess);
|
||||||
|
@ -72,9 +69,6 @@ public class Acia6850 extends Acia {
|
||||||
public void write(int address, int data) throws MemoryAccessException {
|
public void write(int address, int data) throws MemoryAccessException {
|
||||||
switch (address) {
|
switch (address) {
|
||||||
case TX_REG:
|
case TX_REG:
|
||||||
if (cpuAccess) {
|
|
||||||
interrupt = false;
|
|
||||||
}
|
|
||||||
txWrite(data);
|
txWrite(data);
|
||||||
break;
|
break;
|
||||||
case CTRL_REG:
|
case CTRL_REG:
|
||||||
|
@ -119,6 +113,10 @@ public class Acia6850 extends Acia {
|
||||||
stat |= 0x80;
|
stat |= 0x80;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (cpuAccess) {
|
||||||
|
interrupt = false;
|
||||||
|
}
|
||||||
|
|
||||||
return stat;
|
return stat;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -7,7 +7,7 @@ import org.junit.Test;
|
||||||
import static org.junit.Assert.assertEquals;
|
import static org.junit.Assert.assertEquals;
|
||||||
import static org.mockito.Mockito.*;
|
import static org.mockito.Mockito.*;
|
||||||
|
|
||||||
public class AciaTest6850 {
|
public class Acia6850Test {
|
||||||
|
|
||||||
private final static int CMD_STAT_REG = 0;
|
private final static int CMD_STAT_REG = 0;
|
||||||
private final static int DATA_REG = 1;
|
private final static int DATA_REG = 1;
|
||||||
|
@ -91,6 +91,78 @@ public class AciaTest6850 {
|
||||||
verify(mockBus, never()).assertIrq();
|
verify(mockBus, never()).assertIrq();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void shouldTriggerInterruptFlagOnRxFullIfRxIrqEnabled() throws Exception {
|
||||||
|
Bus mockBus = mock(Bus.class);
|
||||||
|
|
||||||
|
Acia acia = newAcia();
|
||||||
|
acia.setBus(mockBus);
|
||||||
|
|
||||||
|
// Disable TX IRQ, Enable RX IRQ
|
||||||
|
acia.write(CMD_STAT_REG, 0x80);
|
||||||
|
|
||||||
|
acia.rxWrite('a');
|
||||||
|
|
||||||
|
// Receive should cause IRQ flag to be set
|
||||||
|
assertEquals(0x80, acia.read(0x0000, true) & 0x80);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void shouldNotTriggerInterruptFlagOnRxFullIfRxIrqNotEnabled() throws Exception {
|
||||||
|
Bus mockBus = mock(Bus.class);
|
||||||
|
|
||||||
|
Acia acia = newAcia();
|
||||||
|
acia.setBus(mockBus);
|
||||||
|
|
||||||
|
// Disable TX IRQ, Disable RX IRQ
|
||||||
|
acia.write(CMD_STAT_REG, 0x00);
|
||||||
|
|
||||||
|
acia.rxWrite('a');
|
||||||
|
|
||||||
|
// Receive should not cause IRQ flag to be set
|
||||||
|
assertEquals(0x00, acia.read(0x0000, true) & 0x80);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void shouldTriggerInterruptFlagOnTxEmptyIfTxIrqEnabled() throws Exception {
|
||||||
|
Bus mockBus = mock(Bus.class);
|
||||||
|
|
||||||
|
Acia acia = newAcia();
|
||||||
|
acia.setBus(mockBus);
|
||||||
|
|
||||||
|
// Enable TX IRQ, Disable RX IRQ
|
||||||
|
acia.write(CMD_STAT_REG, 0x20);
|
||||||
|
|
||||||
|
// Write data
|
||||||
|
acia.write(1, 'a');
|
||||||
|
|
||||||
|
verify(mockBus, never()).assertIrq();
|
||||||
|
|
||||||
|
// Transmission should cause IRQ flag to be set
|
||||||
|
acia.txRead(true);
|
||||||
|
|
||||||
|
assertEquals(0x80, acia.read(0x0000, true) & 0x80);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void shouldNotTriggerInterruptFlagOnTxEmptyIfTxIrqNotEnabled() throws Exception {
|
||||||
|
Bus mockBus = mock(Bus.class);
|
||||||
|
|
||||||
|
Acia acia = newAcia();
|
||||||
|
acia.setBus(mockBus);
|
||||||
|
|
||||||
|
// Disable TX IRQ, Disable RX IRQ
|
||||||
|
acia.write(CMD_STAT_REG, 0x02);
|
||||||
|
|
||||||
|
// Write data
|
||||||
|
acia.write(DATA_REG, 'a');
|
||||||
|
|
||||||
|
// Transmission should not cause IRQ flag to be set
|
||||||
|
acia.txRead(true);
|
||||||
|
|
||||||
|
assertEquals(0x00, acia.read(0x0000, true) & 0x80);
|
||||||
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void newAciaShouldHaveTxEmptyStatus() throws Exception {
|
public void newAciaShouldHaveTxEmptyStatus() throws Exception {
|
||||||
Acia acia = newAcia();
|
Acia acia = newAcia();
|
||||||
|
@ -129,6 +201,24 @@ public class AciaTest6850 {
|
||||||
@Test
|
@Test
|
||||||
public void aciaShouldOverrunAndReadShouldReset()
|
public void aciaShouldOverrunAndReadShouldReset()
|
||||||
throws Exception {
|
throws Exception {
|
||||||
|
|
||||||
|
Acia acia = newAcia();
|
||||||
|
|
||||||
|
// overrun ACIA
|
||||||
|
acia.rxWrite('a');
|
||||||
|
acia.rxWrite('b');
|
||||||
|
|
||||||
|
assertEquals(0x20, acia.read(CMD_STAT_REG, true) & 0x20);
|
||||||
|
|
||||||
|
// read should reset
|
||||||
|
acia.rxRead(true);
|
||||||
|
assertEquals(0x00, acia.read(CMD_STAT_REG, true) & 0x20);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void aciaShouldOverrunAndMemoryWindowReadShouldNotReset()
|
||||||
|
throws Exception {
|
||||||
|
|
||||||
Acia acia = newAcia();
|
Acia acia = newAcia();
|
||||||
|
|
||||||
|
@ -138,9 +228,9 @@ public class AciaTest6850 {
|
||||||
|
|
||||||
assertEquals(0x20, acia.read(CMD_STAT_REG, true) & 0x20);
|
assertEquals(0x20, acia.read(CMD_STAT_REG, true) & 0x20);
|
||||||
|
|
||||||
// read should reset
|
// memory window read should not reset
|
||||||
acia.rxRead(true);
|
acia.rxRead(false);
|
||||||
assertEquals(0x00, acia.read(CMD_STAT_REG, true) & 0x20);
|
assertEquals(0x20, acia.read(CMD_STAT_REG, true) & 0x20);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -73,12 +73,84 @@ public class AciaTest {
|
||||||
// Write data
|
// Write data
|
||||||
acia.write(0, 'a');
|
acia.write(0, 'a');
|
||||||
|
|
||||||
// Transmission should cause IRQ
|
// Transmission should not cause IRQ
|
||||||
acia.txRead(true);
|
acia.txRead(true);
|
||||||
|
|
||||||
verify(mockBus, never()).assertIrq();
|
verify(mockBus, never()).assertIrq();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void shouldTriggerInterruptFlagOnRxFullIfRxIrqEnabled() throws Exception {
|
||||||
|
Bus mockBus = mock(Bus.class);
|
||||||
|
|
||||||
|
Acia acia = new Acia6551(0x000);
|
||||||
|
acia.setBus(mockBus);
|
||||||
|
|
||||||
|
// Disable TX IRQ, Enable RX IRQ
|
||||||
|
acia.write(2, 0x00);
|
||||||
|
|
||||||
|
acia.rxWrite('a');
|
||||||
|
|
||||||
|
// Receive should cause IRQ flag to be set
|
||||||
|
assertEquals(0x80, acia.read(0x0001, true) & 0x80);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void shouldNotTriggerInterruptFlagOnRxFullIfRxIrqNotEnabled() throws Exception {
|
||||||
|
Bus mockBus = mock(Bus.class);
|
||||||
|
|
||||||
|
Acia acia = new Acia6551(0x000);
|
||||||
|
acia.setBus(mockBus);
|
||||||
|
|
||||||
|
// Disable TX IRQ, Disable RX IRQ
|
||||||
|
acia.write(2, 0x02);
|
||||||
|
|
||||||
|
acia.rxWrite('a');
|
||||||
|
|
||||||
|
// Receive should not cause IRQ flag to be set
|
||||||
|
assertEquals(0x00, acia.read(0x0001, true) & 0x80);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void shouldTriggerInterruptFlagOnTxEmptyIfTxIrqEnabled() throws Exception {
|
||||||
|
Bus mockBus = mock(Bus.class);
|
||||||
|
|
||||||
|
Acia acia = new Acia6551(0x000);
|
||||||
|
acia.setBus(mockBus);
|
||||||
|
|
||||||
|
// Enable TX IRQ, Disable RX IRQ
|
||||||
|
acia.write(2, 0x06);
|
||||||
|
|
||||||
|
// Write data
|
||||||
|
acia.write(0, 'a');
|
||||||
|
|
||||||
|
verify(mockBus, never()).assertIrq();
|
||||||
|
|
||||||
|
// Transmission should cause IRQ flag to be set
|
||||||
|
acia.txRead(true);
|
||||||
|
|
||||||
|
assertEquals(0x80, acia.read(0x0001, true) & 0x80);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void shouldNotTriggerInterruptFlagOnTxEmptyIfTxIrqNotEnabled() throws Exception {
|
||||||
|
Bus mockBus = mock(Bus.class);
|
||||||
|
|
||||||
|
Acia acia = new Acia6551(0x000);
|
||||||
|
acia.setBus(mockBus);
|
||||||
|
|
||||||
|
// Disable TX IRQ, Disable RX IRQ
|
||||||
|
acia.write(2, 0x02);
|
||||||
|
|
||||||
|
// Write data
|
||||||
|
acia.write(0, 'a');
|
||||||
|
|
||||||
|
// Transmission should not cause IRQ flag to be set
|
||||||
|
acia.txRead(true);
|
||||||
|
|
||||||
|
assertEquals(0x00, acia.read(0x0001, true) & 0x80);
|
||||||
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void newAciaShouldHaveTxEmptyStatus() throws Exception {
|
public void newAciaShouldHaveTxEmptyStatus() throws Exception {
|
||||||
Acia acia = new Acia6551(0x000);
|
Acia acia = new Acia6551(0x000);
|
||||||
|
|
Loading…
Reference in New Issue
Block a user