1
0
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:
Matt Harlum 2017-06-06 12:15:23 +10:00
parent 3c3aee30a7
commit faf5d22660
3 changed files with 173 additions and 13 deletions

View File

@ -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;
} }

View File

@ -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);
} }

View File

@ -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);