summaryrefslogtreecommitdiffstatshomepage
path: root/src/devices/machine/eeprompar.cpp
diff options
context:
space:
mode:
author AJR <ajrhacker@users.noreply.github.com>2017-08-30 00:17:11 -0400
committer AJR <ajrhacker@users.noreply.github.com>2017-08-30 00:17:11 -0400
commit50749667bb8b6d0b92d187dffc9dcb0a03907375 (patch)
treea35ae42fa7fe7aff6f3c823bc5af724c14aca8af /src/devices/machine/eeprompar.cpp
parentdbae1f4e05cac302e75d3779cf91d9ff8e928f85 (diff)
Improvements to 28XX parallel EEPROM emulation
- Emulate direct manipulation of /OE line for read/write mode control. - Special handling for data polling before a write has completed. - Allow optional configuration of device to lock EEPROM after each write, as often used by Atari. - Eliminate the Atari EEPROM interface devices, since their special features have been incorporated into the base device. To continue using old NVRAM files, rename them from eeprom_eeprom to eeprom.
Diffstat (limited to 'src/devices/machine/eeprompar.cpp')
-rw-r--r--src/devices/machine/eeprompar.cpp102
1 files changed, 99 insertions, 3 deletions
diff --git a/src/devices/machine/eeprompar.cpp b/src/devices/machine/eeprompar.cpp
index 5e63b320add..704decb70ab 100644
--- a/src/devices/machine/eeprompar.cpp
+++ b/src/devices/machine/eeprompar.cpp
@@ -36,11 +36,21 @@
datasheet, for example), and the /WE must be held low for the entire
write/erase duration in order to guarantee the data is written.
+ Though it is possible for the /OE line to be strobed directly upon
+ read accesses, it may also be controlled independently of /CS. For the
+ sake of convenience, the device here can also be configured to emulate
+ a small amount of external circuitry (1/2 of a LS74 flip-flop and 1
+ gate of a LS02 or LS08), typically used by Atari Games, that reasserts
+ /OE low to lock the EEPROM after each byte of data is written and upon
+ reset, with extra writes required to unlock the EEPROM in between.
+
***************************************************************************/
#include "emu.h"
#include "machine/eeprompar.h"
+//#define VERBOSE 1
+#include "logmacro.h"
//**************************************************************************
@@ -89,8 +99,49 @@ void eeprom_parallel_base_device::device_reset()
//-------------------------------------------------
eeprom_parallel_28xx_device::eeprom_parallel_28xx_device(const machine_config &mconfig, device_type devtype, const char *tag, device_t *owner)
- : eeprom_parallel_base_device(mconfig, devtype, tag, owner)
+ : eeprom_parallel_base_device(mconfig, devtype, tag, owner),
+ m_lock_after_write(false),
+ m_oe(-1)
+{
+}
+
+
+//-------------------------------------------------
+// static_set_lock_after_write - configuration
+// helper to enable simulation of external
+// flip-flop hooked to lock EEPROM after writes
+//-------------------------------------------------
+
+void eeprom_parallel_28xx_device::static_set_lock_after_write(device_t &device, bool lock)
+{
+ downcast<eeprom_parallel_28xx_device &>(device).m_lock_after_write = lock;
+}
+
+
+//-------------------------------------------------
+// device_start - device-specific startup
+//-------------------------------------------------
+
+void eeprom_parallel_28xx_device::device_start()
{
+ // start the base class
+ eeprom_parallel_base_device::device_start();
+
+ save_item(NAME(m_oe));
+}
+
+
+//-------------------------------------------------
+// device_reset - device-specific reset
+//-------------------------------------------------
+
+void eeprom_parallel_28xx_device::device_reset()
+{
+ // reset the base class
+ eeprom_parallel_base_device::device_reset();
+
+ if (m_lock_after_write)
+ m_oe = 0;
}
@@ -100,15 +151,60 @@ eeprom_parallel_28xx_device::eeprom_parallel_28xx_device(const machine_config &m
WRITE8_MEMBER(eeprom_parallel_28xx_device::write)
{
- eeprom_base_device::write(offset, data);
+ if (m_oe == 0)
+ {
+ // Master Boy writes every byte twice, resetting a control line in between, for some reason not clear
+ if (internal_read(offset) != data)
+ LOG("%s: Write attempted while /OE active (offset = %X, data = %02X)\n", machine().describe_context(), offset, data);
+ }
+ else
+ {
+ LOG("%s: Write cycle started (offset = %X, data = %02X)\n", machine().describe_context(), offset, data);
+ eeprom_base_device::write(offset, data);
+ if (m_lock_after_write)
+ m_oe = 0;
+ }
}
READ8_MEMBER(eeprom_parallel_28xx_device::read)
{
- return eeprom_base_device::read(offset);
+ if (m_oe == 1)
+ {
+ LOG("%s: Read attempted while /OE inactive (offset = %X)\n", machine().describe_context(), offset);
+ return space.unmap();
+ }
+
+ // if a write has not completed yet, the highest bit of data written will be read back inverted when polling the offset
+ if (ready())
+ return eeprom_base_device::read(offset);
+ else
+ {
+ LOG("%s: Data read back before write completed (offset = %X)\n", machine().describe_context(), offset);
+ return ~internal_read(offset) & 0x80;
+ }
}
+//-------------------------------------------------
+// oe_w - direct write to /OE (true line state)
+//-------------------------------------------------
+
+WRITE_LINE_MEMBER(eeprom_parallel_28xx_device::oe_w)
+{
+ LOG("%s: EEPROM %s for writing\n", machine().describe_context(), state ? "unlocked" : "locked");
+ m_oe = state ? 1 : 0;
+}
+
+
+//-------------------------------------------------
+// unlock_write - unlock EEPROM by deasserting
+// /OE line through external flip-flop
+//-------------------------------------------------
+
+WRITE8_MEMBER(eeprom_parallel_28xx_device::unlock_write) { oe_w(1); }
+WRITE16_MEMBER(eeprom_parallel_28xx_device::unlock_write) { oe_w(1); }
+WRITE32_MEMBER(eeprom_parallel_28xx_device::unlock_write) { oe_w(1); }
+
//**************************************************************************
// DERIVED TYPES