diff options
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 |
commit | 50749667bb8b6d0b92d187dffc9dcb0a03907375 (patch) | |
tree | a35ae42fa7fe7aff6f3c823bc5af724c14aca8af /src/devices/machine/eeprompar.cpp | |
parent | dbae1f4e05cac302e75d3779cf91d9ff8e928f85 (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.cpp | 102 |
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 |