diff options
Diffstat (limited to 'trunk/src/emu/machine/nmc9306.c')
-rw-r--r-- | trunk/src/emu/machine/nmc9306.c | 322 |
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; +} |