summaryrefslogtreecommitdiffstatshomepage
path: root/trunk/src/emu/machine/nmc9306.c
diff options
context:
space:
mode:
Diffstat (limited to 'trunk/src/emu/machine/nmc9306.c')
-rw-r--r--trunk/src/emu/machine/nmc9306.c322
1 files changed, 322 insertions, 0 deletions
diff --git a/trunk/src/emu/machine/nmc9306.c b/trunk/src/emu/machine/nmc9306.c
new file mode 100644
index 00000000000..627f282bd93
--- /dev/null
+++ b/trunk/src/emu/machine/nmc9306.c
@@ -0,0 +1,322 @@
+/**********************************************************************
+
+ National Semiconductor NMC9306 256-Bit Serial EEPROM emulation
+
+ Copyright MESS Team.
+ Visit http://mamedev.org for licensing and usage restrictions.
+
+**********************************************************************/
+
+#include "emu.h"
+#include "nmc9306.h"
+#include "machine/devhelpr.h"
+
+
+
+//**************************************************************************
+// MACROS / CONSTANTS
+//**************************************************************************
+
+#define LOG 1
+
+#define RAM_SIZE 32
+
+
+// instructions
+enum
+{
+ OTHER = 0,
+ WRITE, // write register A3A2A1A0
+ READ, // read register A3A2A1A0
+ ERASE // erase register A3A2A1A0
+};
+
+// other instructions
+enum
+{
+ EWDS = 0, // erase/write disable
+ WRAL, // write all registers
+ ERAL, // erase all registers
+ EWEN, // erase/write enable
+};
+
+// states
+enum
+{
+ STATE_IDLE = 0,
+ STATE_COMMAND,
+ STATE_ADDRESS,
+ STATE_DATA_IN,
+ STATE_DATA_OUT,
+ STATE_ERASE
+};
+
+
+
+//**************************************************************************
+// INLINE HELPERS
+//**************************************************************************
+
+// device type definition
+const device_type NMC9306 = &device_creator<nmc9306_device>;
+
+//-------------------------------------------------
+// nmc9306_device - constructor
+//-------------------------------------------------
+
+inline UINT16 nmc9306_device::read(offs_t offset)
+{
+ return m_register[offset];
+}
+
+
+//-------------------------------------------------
+// nmc9306_device - constructor
+//-------------------------------------------------
+
+inline void nmc9306_device::write(offs_t offset, UINT16 data)
+{
+ if (m_ewen)
+ {
+ m_register[offset] &= data;
+ }
+}
+
+
+//-------------------------------------------------
+// nmc9306_device - constructor
+//-------------------------------------------------
+
+inline void nmc9306_device::erase(offs_t offset)
+{
+ if (m_ewen)
+ {
+ m_register[offset] = 0xffff;
+ }
+}
+
+
+
+//**************************************************************************
+// LIVE DEVICE
+//**************************************************************************
+
+//-------------------------------------------------
+// nmc9306_device - constructor
+//-------------------------------------------------
+
+nmc9306_device::nmc9306_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock)
+ : device_t(mconfig, NMC9306, "NMC9306", tag, owner, clock),
+ device_nvram_interface(mconfig, *this),
+ m_state(STATE_IDLE),
+ m_ewen(false)
+{
+}
+
+
+//-------------------------------------------------
+// device_start - device-specific startup
+//-------------------------------------------------
+
+void nmc9306_device::device_start()
+{
+ // state saving
+ save_item(NAME(m_bits));
+ save_item(NAME(m_state));
+ save_item(NAME(m_command));
+ save_item(NAME(m_address));
+ save_item(NAME(m_data));
+ save_item(NAME(m_ewen));
+ save_item(NAME(m_cs));
+ save_item(NAME(m_sk));
+ save_item(NAME(m_do));
+ save_item(NAME(m_di));
+}
+
+
+//-------------------------------------------------
+// nvram_default - called to initialize NVRAM to
+// its default state
+//-------------------------------------------------
+
+void nmc9306_device::nvram_default()
+{
+}
+
+
+//-------------------------------------------------
+// nvram_read - called to read NVRAM from the
+// .nv file
+//-------------------------------------------------
+
+void nmc9306_device::nvram_read(emu_file &file)
+{
+ file.read(m_register, RAM_SIZE);
+}
+
+
+//-------------------------------------------------
+// nvram_write - called to write NVRAM to the
+// .nv file
+//-------------------------------------------------
+
+void nmc9306_device::nvram_write(emu_file &file)
+{
+ file.write(m_register, RAM_SIZE);
+}
+
+
+//-------------------------------------------------
+// cs_w - chip select input
+//-------------------------------------------------
+
+WRITE_LINE_MEMBER( nmc9306_device::cs_w )
+{
+ m_cs = state;
+}
+
+
+//-------------------------------------------------
+// ck_w - serial clock input
+//-------------------------------------------------
+
+WRITE_LINE_MEMBER( nmc9306_device::sk_w )
+{
+ m_sk = state;
+
+ if (!m_cs || !m_sk) return;
+
+ switch (m_state)
+ {
+ case STATE_IDLE:
+ if (LOG) logerror("NMC9306 '%s' Idle %u\n", tag(), m_di);
+
+ if (m_di)
+ {
+ // start bit received
+ m_state = STATE_COMMAND;
+ m_bits = 0;
+ }
+ break;
+
+ case STATE_COMMAND:
+ if (LOG) logerror("NMC9306 '%s' Command Bit %u\n", tag(), m_di);
+
+ m_command <<= 1;
+ m_command |= m_di;
+ m_bits++;
+
+ if (m_bits == 4)
+ {
+ m_state = STATE_ADDRESS;
+ m_bits = 0;
+ }
+ break;
+
+ case STATE_ADDRESS:
+ if (LOG) logerror("NMC9306 '%s' Address Bit %u\n", tag(), m_di);
+
+ m_address <<= 1;
+ m_address |= m_di;
+ m_bits++;
+
+ if (m_bits == 4)
+ {
+ switch ((m_command >> 2) & 0x03)
+ {
+ case OTHER:
+ switch (m_command & 0x03)
+ {
+ case EWDS:
+ if (LOG) logerror("NMC9306 '%s' EWDS\n", tag());
+ m_ewen = false;
+ m_state = STATE_IDLE;
+ break;
+
+ case WRAL:
+ if (LOG) logerror("NMC9306 '%s' WRAL\n", tag());
+ break;
+
+ case ERAL:
+ if (LOG) logerror("NMC9306 '%s' ERAL\n", tag());
+ break;
+
+ case EWEN:
+ if (LOG) logerror("NMC9306 '%s' EWEN\n", tag());
+ m_ewen = true;
+ m_state = STATE_IDLE;
+ break;
+ }
+ break;
+
+ case WRITE:
+ if (LOG) logerror("NMC9306 '%s' WRITE %u\n", tag(), m_address & 0x0f);
+ m_state = STATE_DATA_IN;
+ break;
+
+ case READ:
+ if (LOG) logerror("NMC9306 '%s' READ %u\n", tag(), m_address & 0x0f);
+ m_data = read(m_address & 0x0f);
+ m_state = STATE_DATA_OUT;
+ break;
+
+ case ERASE:
+ if (LOG) logerror("NMC9306 '%s' ERASE %u\n", tag(), m_address & 0x0f);
+ erase(m_address & 0x0f);
+ m_state = STATE_ERASE;
+ break;
+ }
+
+ m_bits = 0;
+ }
+ break;
+
+ case STATE_DATA_IN:
+ if (LOG) logerror("NMC9306 '%s' Data Bit IN %u\n", tag(), m_di);
+
+ m_data <<= 1;
+ m_data |= m_di;
+ m_bits++;
+
+ if (m_bits == 16)
+ {
+ write(m_address & 0x0f, m_data);
+
+ m_state = STATE_IDLE;
+ }
+ break;
+
+ case STATE_DATA_OUT:
+ if (LOG) logerror("NMC9306 '%s' Data Bit OUT %u\n", tag(), m_di);
+
+ m_do = BIT(m_data, 15);
+ m_data <<= 1;
+ m_bits++;
+
+ if (m_bits == 16)
+ {
+ m_state = STATE_IDLE;
+ }
+ break;
+ }
+}
+
+
+//-------------------------------------------------
+// di_w - serial data input
+//-------------------------------------------------
+
+WRITE_LINE_MEMBER( nmc9306_device::di_w )
+{
+ m_di = state;
+}
+
+
+//-------------------------------------------------
+// do_r - serial data output
+//-------------------------------------------------
+
+READ_LINE_MEMBER( nmc9306_device::do_r )
+{
+ return m_do;
+}