From 5df775bbb02c84f237aae50b0279c9fca2ea85da Mon Sep 17 00:00:00 2001 From: Tim Allen Date: Mon, 29 May 2023 22:24:04 +1000 Subject: [PATCH] Make the emulated 6551's soft ("program") reset state match the MOS datasheet. The only description of the effects of "program reset" in the original MOS datasheet is in the section for each register. The W65C51S and W65C51N datasheets have a heading "PROGRAM RESET OPERATION", but it amounts to: - internal registers are modified as described in the section for each register - changes to the DTR, DCD, and DSR pins which Symon does not emulate - the overrun flag is cleared ...which is what this new implementation does. It would make *sense* for the reset to do things like "cancel transmission or reception in progress" and stop asserting an interrupt, as the old code did, but I can't find any evidence of such behaviour in the datasheets. --- .../com/loomcom/symon/devices/Acia6551.java | 19 ++++--- src/test/java/com/loomcom/symon/AciaTest.java | 51 +++++++++++++++++++ 2 files changed, 62 insertions(+), 8 deletions(-) diff --git a/src/main/java/com/loomcom/symon/devices/Acia6551.java b/src/main/java/com/loomcom/symon/devices/Acia6551.java index c596bf7..26902be 100644 --- a/src/main/java/com/loomcom/symon/devices/Acia6551.java +++ b/src/main/java/com/loomcom/symon/devices/Acia6551.java @@ -211,13 +211,16 @@ public class Acia6551 extends Acia { private synchronized void reset() { - txChar = 0; - txEmpty = true; - rxChar = 0; - rxFull = false; - receiveIrqEnabled = false; - transmitIrqEnabled = false; - interrupt = false; - } + // Figure 6 in the 6551 ACIA data sheet says the "program reset" + // event does not modify the control register. + // Figure 7 in the 6551 ACIA data sheet says the "program reset" + // event keeps the "parity check" configuration in the command + // register, but resets the other bits to defaults. + setCommandRegister((commandRegister & 0xe0) | 0x02); + + // Figure 8 in the 6551 ACIA data sheet says the "program reset" + // event clears the "overrun" flag but otherwise has no effect. + overrun = false; + } } diff --git a/src/test/java/com/loomcom/symon/AciaTest.java b/src/test/java/com/loomcom/symon/AciaTest.java index 309ce89..17deaa7 100644 --- a/src/test/java/com/loomcom/symon/AciaTest.java +++ b/src/test/java/com/loomcom/symon/AciaTest.java @@ -275,4 +275,55 @@ public class AciaTest { assertEquals(0x00, acia.read(0x0003, false)); } + + @Test + public void programResetClearsOverrunStatus() throws Exception { + Acia6551 acia = new Acia6551(0x0000); + Bus bus = new Bus(acia.ACIA_SIZE); + acia.setBus(bus); + + // Change as many status bits as we can. + acia.write(0x0002, 0x00); // enable receive interrupt + acia.rxWrite('a'); + acia.rxWrite('b'); // overrun, receive full, interrupt signalled + acia.write(0x0000, 'c'); // Transmitter Data Register not empty + + // Check that all the bits we expected to be set actually are + assertEquals(0x8C, acia.read(0x0001, false)); + + // Do a "program reset". The value is ignored. + acia.write(0x0001, 0xFF); + + // Check that only bit 2 was cleared. + assertEquals(0x88, acia.read(0x0001, false)); + } + + @Test + public void programResetKeepsParitySettings() throws Exception { + Acia6551 acia = new Acia6551(0x0000); + + // Set all the command register bits + acia.write(0x0002, 0xFF); + + // Do a "program reset". The value is ignored. + acia.write(0x0001, 0xFF); + + // The top 3 bits should be kept as-is, + // the bottom 5 bits should be reset to defaults. + assertEquals(0xE2, acia.read(0x0002, false)); + } + + @Test + public void programResetLeavesControlRegisterUnchanged() throws Exception { + Acia6551 acia = new Acia6551(0x0000); + + // Set all the control register bits + acia.write(0x0003, 0xFF); + + // Do a "program reset". The value is ignored. + acia.write(0x0001, 0xFF); + + // No bits should have changed. + assertEquals(0xFF, acia.read(0x0003, false)); + } }