summaryrefslogtreecommitdiffstatshomepage
diff options
context:
space:
mode:
author Curt Coder <curtcoder@mail.com>2011-04-17 14:10:26 +0000
committer Curt Coder <curtcoder@mail.com>2011-04-17 14:10:26 +0000
commit4f3f0decb8a43cf1b36975d0948f9fe7c1d6e5fc (patch)
tree41b7eb4bb41e281e6f5f2c28ca5941cb149bb867
parentc97228231910c57b5ce8f7b31aa2fe7a598ae931 (diff)
Imported MSM5832 RTC from MESS. (no whatsnew)
-rw-r--r--.gitattributes4
-rw-r--r--src/emu/emu.mak1
-rw-r--r--src/emu/msm5832.c375
-rw-r--r--src/emu/msm5832.h118
-rw-r--r--src/emu/msm58321.c450
-rw-r--r--src/emu/msm58321.h140
6 files changed, 1088 insertions, 0 deletions
diff --git a/.gitattributes b/.gitattributes
index 76a894efc21..037394db925 100644
--- a/.gitattributes
+++ b/.gitattributes
@@ -928,6 +928,10 @@ src/emu/mconfig.h svneol=native#text/plain
src/emu/memconv.h svneol=native#text/plain
src/emu/memory.c svneol=native#text/plain
src/emu/memory.h svneol=native#text/plain
+src/emu/msm5832.c svneol=native#text/plain
+src/emu/msm5832.h svneol=native#text/plain
+src/emu/msm58321.c svneol=native#text/plain
+src/emu/msm58321.h svneol=native#text/plain
src/emu/output.c svneol=native#text/plain
src/emu/output.h svneol=native#text/plain
src/emu/profiler.c svneol=native#text/plain
diff --git a/src/emu/emu.mak b/src/emu/emu.mak
index ac0418506e5..2c6150ff99b 100644
--- a/src/emu/emu.mak
+++ b/src/emu/emu.mak
@@ -193,6 +193,7 @@ EMUMACHINEOBJS = \
$(EMUMACHINE)/mc146818.o \
$(EMUMACHINE)/mc6852.o \
$(EMUMACHINE)/mc68901.o \
+ $(EMUMACHINE)/msm5832.o \
$(EMUMACHINE)/msm58321.o \
$(EMUMACHINE)/microtch.o \
$(EMUMACHINE)/mos6529.o \
diff --git a/src/emu/msm5832.c b/src/emu/msm5832.c
new file mode 100644
index 00000000000..2ef1d661f89
--- /dev/null
+++ b/src/emu/msm5832.c
@@ -0,0 +1,375 @@
+/**********************************************************************
+
+ OKI MSM5832 Real Time Clock/Calendar emulation
+
+ Copyright MESS Team.
+ Visit http://mamedev.org for licensing and usage restrictions.
+
+**********************************************************************/
+
+/*
+
+ TODO:
+
+ - 12/24 hour
+ - AM/PM
+ - leap year
+ - test input
+ - reference signal output
+
+*/
+
+#include "msm5832.h"
+#include "machine/devhelpr.h"
+
+
+
+//**************************************************************************
+// MACROS / CONSTANTS
+//**************************************************************************
+
+#define LOG 0
+
+
+// registers
+enum
+{
+ REGISTER_S1 = 0,
+ REGISTER_S10,
+ REGISTER_MI1,
+ REGISTER_MI10,
+ REGISTER_H1,
+ REGISTER_H10,
+ REGISTER_W,
+ REGISTER_D1,
+ REGISTER_D10,
+ REGISTER_MO1,
+ REGISTER_MO10,
+ REGISTER_Y1,
+ REGISTER_Y10,
+ REGISTER_REF = 15
+};
+
+
+// days per month
+static const int DAYS_PER_MONTH[12] = { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 };
+
+
+
+//**************************************************************************
+// GLOBAL VARIABLES
+//**************************************************************************
+
+// devices
+const device_type MSM5832 = msm5832_device_config::static_alloc_device_config;
+
+
+
+//**************************************************************************
+// DEVICE CONFIGURATION
+//**************************************************************************
+
+GENERIC_DEVICE_CONFIG_SETUP(msm5832, "MSM5832")
+
+
+
+//**************************************************************************
+// INLINE HELPERS
+//**************************************************************************
+
+//-------------------------------------------------
+// read_counter -
+//-------------------------------------------------
+
+inline int msm5832_device::read_counter(int counter)
+{
+ return (m_reg[counter + 1] * 10) + m_reg[counter];
+}
+
+
+//-------------------------------------------------
+// write_counter -
+//-------------------------------------------------
+
+inline void msm5832_device::write_counter(int counter, int value)
+{
+ m_reg[counter] = value % 10;
+ m_reg[counter + 1] = value / 10;
+}
+
+
+//-------------------------------------------------
+// advance_seconds -
+//-------------------------------------------------
+
+inline void msm5832_device::advance_seconds()
+{
+ int seconds = read_counter(REGISTER_S1);
+
+ seconds++;
+
+ if (seconds > 59)
+ {
+ seconds = 0;
+
+ advance_minutes();
+ }
+
+ write_counter(REGISTER_S1, seconds);
+}
+
+
+//-------------------------------------------------
+// advance_minutes -
+//-------------------------------------------------
+
+inline void msm5832_device::advance_minutes()
+{
+ int minutes = read_counter(REGISTER_MI1);
+ int hours = read_counter(REGISTER_H1);
+ int days = read_counter(REGISTER_D1);
+ int month = read_counter(REGISTER_MO1);
+ int year = read_counter(REGISTER_Y1);
+ int day_of_week = m_reg[REGISTER_W];
+
+ minutes++;
+
+ if (minutes > 59)
+ {
+ minutes = 0;
+ hours++;
+ }
+
+ if (hours > 23)
+ {
+ hours = 0;
+ days++;
+ day_of_week++;
+ }
+
+ if (day_of_week > 6)
+ {
+ day_of_week++;
+ }
+
+ if (days > DAYS_PER_MONTH[month - 1])
+ {
+ days = 1;
+ month++;
+ }
+
+ if (month > 12)
+ {
+ month = 1;
+ year++;
+ }
+
+ if (year > 99)
+ {
+ year = 0;
+ }
+
+ write_counter(REGISTER_MI1, minutes);
+ write_counter(REGISTER_H1, hours);
+ write_counter(REGISTER_D1, days);
+ write_counter(REGISTER_MO1, month);
+ write_counter(REGISTER_Y1, year);
+ m_reg[REGISTER_W] = day_of_week;
+}
+
+
+
+//**************************************************************************
+// LIVE DEVICE
+//**************************************************************************
+
+//-------------------------------------------------
+// msm5832_device - constructor
+//-------------------------------------------------
+
+msm5832_device::msm5832_device(running_machine &_machine, const msm5832_device_config &config)
+ : device_t(_machine, config),
+ m_hold(0),
+ m_address(0),
+ m_read(0),
+ m_write(0),
+ m_cs(0),
+ m_config(config)
+{
+ for (int i = 0; i < 13; i++)
+ m_reg[i] = 0;
+}
+
+
+//-------------------------------------------------
+// device_start - device-specific startup
+//-------------------------------------------------
+
+void msm5832_device::device_start()
+{
+ // allocate timers
+ m_clock_timer = timer_alloc(TIMER_CLOCK);
+ m_clock_timer->adjust(attotime::from_hz(clock() / 32768), 0, attotime::from_hz(clock() / 32768));
+
+ // state saving
+ save_item(NAME(m_reg));
+ save_item(NAME(m_hold));
+ save_item(NAME(m_address));
+ save_item(NAME(m_read));
+ save_item(NAME(m_write));
+ save_item(NAME(m_cs));
+}
+
+
+//-------------------------------------------------
+// device_timer - handler timer events
+//-------------------------------------------------
+
+void msm5832_device::device_timer(emu_timer &timer, device_timer_id id, int param, void *ptr)
+{
+ switch (id)
+ {
+ case TIMER_CLOCK:
+ if (!m_hold)
+ {
+ advance_seconds();
+ }
+ break;
+ }
+}
+
+
+//-------------------------------------------------
+// data_r -
+//-------------------------------------------------
+
+READ8_MEMBER( msm5832_device::data_r )
+{
+ UINT8 data = 0;
+
+ if (m_cs && m_read)
+ {
+ if (m_address == REGISTER_REF)
+ {
+ // TODO reference output
+ }
+ else
+ {
+ data = m_reg[m_address];
+ }
+ }
+
+ if (LOG) logerror("MSM5832 '%s' Register Read %01x: %01x\n", tag(), m_address, data & 0x0f);
+
+ return data & 0x0f;
+}
+
+
+//-------------------------------------------------
+// data_w -
+//-------------------------------------------------
+
+WRITE8_MEMBER( msm5832_device::data_w )
+{
+ if (LOG) logerror("MSM5832 '%s' Register Write %01x: %01x\n", tag(), m_address, data & 0x0f);
+
+ if (m_cs && m_write)
+ {
+ m_reg[m_address] = data & 0x0f;
+ }
+}
+
+
+//-------------------------------------------------
+// address_w -
+//-------------------------------------------------
+
+void msm5832_device::address_w(UINT8 data)
+{
+ if (LOG) logerror("MSM5832 '%s' Address: %01x\n", tag(), data & 0x0f);
+
+ m_address = data & 0x0f;
+}
+
+
+//-------------------------------------------------
+// adj_w -
+//-------------------------------------------------
+
+WRITE_LINE_MEMBER( msm5832_device::adj_w )
+{
+ if (LOG) logerror("MSM5832 '%s' 30 ADJ: %u\n", tag(), state);
+
+ if (state)
+ {
+ int seconds = read_counter(REGISTER_S1);
+
+ if (seconds < 30)
+ {
+ write_counter(REGISTER_S1, 0);
+ }
+ else
+ {
+ write_counter(REGISTER_S1, 0);
+ advance_minutes();
+ }
+ }
+}
+
+
+//-------------------------------------------------
+// test_w -
+//-------------------------------------------------
+
+WRITE_LINE_MEMBER( msm5832_device::test_w )
+{
+ if (LOG) logerror("MSM5832 '%s' TEST: %u\n", tag(), state);
+}
+
+
+//-------------------------------------------------
+// hold_w -
+//-------------------------------------------------
+
+WRITE_LINE_MEMBER( msm5832_device::hold_w )
+{
+ if (LOG) logerror("MSM5832 '%s' HOLD: %u\n", tag(), state);
+
+ m_hold = state;
+}
+
+
+//-------------------------------------------------
+// read_w -
+//-------------------------------------------------
+
+WRITE_LINE_MEMBER( msm5832_device::read_w )
+{
+ if (LOG) logerror("MSM5832 '%s' READ: %u\n", tag(), state);
+
+ m_read = state;
+}
+
+
+//-------------------------------------------------
+// write_w -
+//-------------------------------------------------
+
+WRITE_LINE_MEMBER( msm5832_device::write_w )
+{
+ if (LOG) logerror("MSM5832 '%s' WR: %u\n", tag(), state);
+
+ m_write = state;
+}
+
+
+//-------------------------------------------------
+// cs_w -
+//-------------------------------------------------
+
+WRITE_LINE_MEMBER( msm5832_device::cs_w )
+{
+ if (LOG) logerror("MSM5832 '%s' CS: %u\n", tag(), state);
+
+ m_cs = state;
+}
diff --git a/src/emu/msm5832.h b/src/emu/msm5832.h
new file mode 100644
index 00000000000..4b6b39bf301
--- /dev/null
+++ b/src/emu/msm5832.h
@@ -0,0 +1,118 @@
+/**********************************************************************
+
+ OKI MSM5832 Real Time Clock/Calendar emulation
+
+ Copyright MESS Team.
+ Visit http://mamedev.org for licensing and usage restrictions.
+
+**********************************************************************
+ _____ _____
+ Vdd 1 |* \_/ | 18 HOLD
+ WRITE 2 | | 17 _XT
+ READ 3 | | 16 XT
+ A0 4 | | 15 +- 30 ADJ
+ A1 5 | MSM5832 | 14 TEST
+ A2 6 | | 13 GND
+ A3 7 | | 12 D3
+ CS 8 | | 11 D2
+ D0 9 |_____________| 10 D1
+
+**********************************************************************/
+
+#pragma once
+
+#ifndef __MSM5832__
+#define __MSM5832__
+
+#include "emu.h"
+
+
+
+//**************************************************************************
+// INTERFACE CONFIGURATION MACROS
+//**************************************************************************
+
+#define MCFG_MSM5832_ADD(_tag, _clock) \
+ MCFG_DEVICE_ADD(_tag, MSM5832, _clock)
+
+
+
+//**************************************************************************
+// TYPE DEFINITIONS
+//**************************************************************************
+
+// ======================> msm5832_device_config
+
+class msm5832_device_config : public device_config
+{
+ friend class msm5832_device;
+
+ // construction/destruction
+ msm5832_device_config(const machine_config &mconfig, const char *tag, const device_config *owner, UINT32 clock);
+
+public:
+ // allocators
+ static device_config *static_alloc_device_config(const machine_config &mconfig, const char *tag, const device_config *owner, UINT32 clock);
+ virtual device_t *alloc_device(running_machine &machine) const;
+};
+
+
+
+// ======================> msm5832_device
+
+class msm5832_device : public device_t
+{
+ friend class msm5832_device_config;
+
+ // construction/destruction
+ msm5832_device(running_machine &_machine, const msm5832_device_config &_config);
+
+public:
+ DECLARE_READ8_MEMBER( data_r );
+ DECLARE_WRITE8_MEMBER( data_w );
+
+ void address_w(UINT8 data);
+
+ DECLARE_WRITE_LINE_MEMBER( adj_w );
+ DECLARE_WRITE_LINE_MEMBER( test_w );
+ DECLARE_WRITE_LINE_MEMBER( hold_w );
+
+ DECLARE_WRITE_LINE_MEMBER( read_w );
+ DECLARE_WRITE_LINE_MEMBER( write_w );
+ DECLARE_WRITE_LINE_MEMBER( cs_w );
+
+protected:
+ // device-level overrides
+ virtual void device_start();
+ virtual void device_timer(emu_timer &timer, device_timer_id id, int param, void *ptr);
+
+private:
+ static const device_timer_id TIMER_CLOCK = 0;
+
+ inline int read_counter(int counter);
+ inline void write_counter(int counter, int value);
+ inline void advance_seconds();
+ inline void advance_minutes();
+
+ UINT8 m_reg[13]; // registers
+
+ int m_hold; // counter hold
+ int m_address; // address
+
+ int m_read;
+ int m_write;
+ int m_cs;
+
+ // timers
+ emu_timer *m_clock_timer;
+
+ const msm5832_device_config &m_config;
+};
+
+
+// device type definition
+extern const device_type MSM5832;
+
+
+
+#endif
diff --git a/src/emu/msm58321.c b/src/emu/msm58321.c
new file mode 100644
index 00000000000..4dfc101cbf6
--- /dev/null
+++ b/src/emu/msm58321.c
@@ -0,0 +1,450 @@
+/**********************************************************************
+
+ OKI MSM58321RS Real Time Clock/Calendar emulation
+
+ Copyright MESS Team.
+ Visit http://mamedev.org for licensing and usage restrictions.
+
+**********************************************************************/
+
+/*
+
+ TODO:
+
+ - 12/24 hour
+ - AM/PM
+ - leap year
+ - stop
+ - reset
+ - reference registers
+
+*/
+
+#include "msm58321.h"
+#include "machine/devhelpr.h"
+
+
+
+//**************************************************************************
+// MACROS / CONSTANTS
+//**************************************************************************
+
+#define LOG 1
+
+
+// registers
+enum
+{
+ REGISTER_S1 = 0,
+ REGISTER_S10,
+ REGISTER_MI1,
+ REGISTER_MI10,
+ REGISTER_H1,
+ REGISTER_H10,
+ REGISTER_W,
+ REGISTER_D1,
+ REGISTER_D10,
+ REGISTER_MO1,
+ REGISTER_MO10,
+ REGISTER_Y1,
+ REGISTER_Y10,
+ REGISTER_RESET,
+ REGISTER_REF0,
+ REGISTER_REF1
+};
+
+
+// days per month
+static const int DAYS_PER_MONTH[12] = { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 };
+
+
+
+//**************************************************************************
+// GLOBAL VARIABLES
+//**************************************************************************
+
+// devices
+const device_type MSM58321 = msm58321_device_config::static_alloc_device_config;
+
+
+
+//**************************************************************************
+// DEVICE CONFIGURATION
+//**************************************************************************
+
+GENERIC_DEVICE_CONFIG_SETUP(msm58321, "MSM58321")
+
+
+//-------------------------------------------------
+// device_config_complete - perform any
+// operations now that the configuration is
+// complete
+//-------------------------------------------------
+
+void msm58321_device_config::device_config_complete()
+{
+ // inherit a copy of the static data
+ const msm58321_interface *intf = reinterpret_cast<const msm58321_interface *>(static_config());
+ if (intf != NULL)
+ *static_cast<msm58321_interface *>(this) = *intf;
+
+ // or initialize to defaults if none provided
+ else
+ {
+ memset(&m_out_busy_func, 0, sizeof(m_out_busy_func));
+ }
+}
+
+
+
+//**************************************************************************
+// INLINE HELPERS
+//**************************************************************************
+
+//-------------------------------------------------
+// read_counter -
+//-------------------------------------------------
+
+inline int msm58321_device::read_counter(int counter)
+{
+ return (m_reg[counter + 1] * 10) + m_reg[counter];
+}
+
+
+//-------------------------------------------------
+// write_counter -
+//-------------------------------------------------
+
+inline void msm58321_device::write_counter(int counter, int value)
+{
+ m_reg[counter] = value % 10;
+ m_reg[counter + 1] = value / 10;
+}
+
+
+//-------------------------------------------------
+// advance_seconds -
+//-------------------------------------------------
+
+inline void msm58321_device::advance_seconds()
+{
+ int seconds = read_counter(REGISTER_S1);
+
+ seconds++;
+
+ if (seconds > 59)
+ {
+ seconds = 0;
+
+ advance_minutes();
+ }
+
+ write_counter(REGISTER_S1, seconds);
+}
+
+
+//-------------------------------------------------
+// advance_minutes -
+//-------------------------------------------------
+
+inline void msm58321_device::advance_minutes()
+{
+ int minutes = read_counter(REGISTER_MI1);
+ int hours = read_counter(REGISTER_H1);
+ int days = read_counter(REGISTER_D1);
+ int month = read_counter(REGISTER_MO1);
+ int year = read_counter(REGISTER_Y1);
+ int day_of_week = m_reg[REGISTER_W];
+
+ minutes++;
+
+ if (minutes > 59)
+ {
+ minutes = 0;
+ hours++;
+ }
+
+ if (hours > 23)
+ {
+ hours = 0;
+ days++;
+ day_of_week++;
+ }
+
+ if (day_of_week > 6)
+ {
+ day_of_week++;
+ }
+
+ if (days > DAYS_PER_MONTH[month - 1])
+ {
+ days = 1;
+ month++;
+ }
+
+ if (month > 12)
+ {
+ month = 1;
+ year++;
+ }
+
+ if (year > 99)
+ {
+ year = 0;
+ }
+
+ write_counter(REGISTER_MI1, minutes);
+ write_counter(REGISTER_H1, hours);
+ write_counter(REGISTER_D1, days);
+ write_counter(REGISTER_MO1, month);
+ write_counter(REGISTER_Y1, year);
+ m_reg[REGISTER_W] = day_of_week;
+}
+
+
+
+//**************************************************************************
+// LIVE DEVICE
+//**************************************************************************
+
+//-------------------------------------------------
+// msm58321_device - constructor
+//-------------------------------------------------
+
+msm58321_device::msm58321_device(running_machine &_machine, const msm58321_device_config &config)
+ : device_t(_machine, config),
+ m_config(config)
+{
+ for (int i = 0; i < 13; i++)
+ m_reg[i] = 0;
+}
+
+
+//-------------------------------------------------
+// device_start - device-specific startup
+//-------------------------------------------------
+
+void msm58321_device::device_start()
+{
+ // resolve callbacks
+ devcb_resolve_write_line(&m_out_busy_func, &m_config.m_out_busy_func, this);
+
+ // allocate timers
+ m_clock_timer = timer_alloc(TIMER_CLOCK);
+ m_clock_timer->adjust(attotime::from_hz(clock() / 32768), 0, attotime::from_hz(clock() / 32768));
+
+ m_busy_timer = timer_alloc(TIMER_BUSY);
+ m_busy_timer->adjust(attotime::from_hz(clock() / 16384), 0, attotime::from_hz(clock() / 16384));
+
+ // state saving
+ save_item(NAME(m_cs1));
+ save_item(NAME(m_cs2));
+ save_item(NAME(m_busy));
+ save_item(NAME(m_read));
+ save_item(NAME(m_write));
+ save_item(NAME(m_address_write));
+ save_item(NAME(m_reg));
+ save_item(NAME(m_latch));
+ save_item(NAME(m_address));
+}
+
+
+//-------------------------------------------------
+// device_timer - handler timer events
+//-------------------------------------------------
+
+void msm58321_device::device_timer(emu_timer &timer, device_timer_id id, int param, void *ptr)
+{
+ switch (id)
+ {
+ case TIMER_CLOCK:
+ advance_seconds();
+ break;
+
+ case TIMER_BUSY:
+ devcb_call_write_line(&m_out_busy_func, m_busy);
+ m_busy = !m_busy;
+ break;
+ }
+}
+
+
+//-------------------------------------------------
+// read -
+//-------------------------------------------------
+
+READ8_MEMBER( msm58321_device::read )
+{
+ UINT8 data = 0;
+
+ if (m_cs1 && m_cs2)
+ {
+ if (m_read)
+ {
+ switch (m_address)
+ {
+ case REGISTER_RESET:
+ break;
+
+ case REGISTER_REF0:
+ case REGISTER_REF1:
+ break;
+
+ default:
+ data = m_reg[m_address];
+ break;
+ }
+ }
+
+ if (m_write)
+ {
+ if (m_address >= REGISTER_REF0)
+ {
+ // TODO: output reference values
+ }
+ }
+ }
+
+ if (LOG) logerror("MSM58321 '%s' Register Read %01x: %01x\n", tag(), m_address, data & 0x0f);
+
+ return data;
+}
+
+
+//-------------------------------------------------
+// write -
+//-------------------------------------------------
+
+WRITE8_MEMBER( msm58321_device::write )
+{
+ // latch data for future use
+ m_latch = data & 0x0f;
+
+ if (!m_cs1 || !m_cs2) return;
+
+ if (m_address_write)
+ {
+ if (LOG) logerror("MSM58321 '%s' Latch Address %01x\n", tag(), m_latch);
+
+ // latch address
+ m_address = m_latch;
+ }
+
+ if (m_write)
+ {
+ switch(m_address)
+ {
+ case REGISTER_RESET:
+ if (LOG) logerror("MSM58321 '%s' Reset\n", tag());
+ break;
+
+ case REGISTER_REF0:
+ case REGISTER_REF1:
+ if (LOG) logerror("MSM58321 '%s' Reference Signal\n", tag());
+ break;
+
+ default:
+ if (LOG) logerror("MSM58321 '%s' Register Write %01x: %01x\n", tag(), m_address, data & 0x0f);
+ m_reg[m_address] = m_latch & 0x0f;
+ break;
+ }
+ }
+}
+
+
+//-------------------------------------------------
+// cs1_w -
+//-------------------------------------------------
+
+WRITE_LINE_MEMBER( msm58321_device::cs1_w )
+{
+ if (LOG) logerror("MSM58321 '%s' CS1: %u\n", tag(), state);
+
+ m_cs1 = state;
+}
+
+
+//-------------------------------------------------
+// cs2_w -
+//-------------------------------------------------
+
+WRITE_LINE_MEMBER( msm58321_device::cs2_w )
+{
+ if (LOG) logerror("MSM58321 '%s' CS2: %u\n", tag(), state);
+
+ m_cs2 = state;
+}
+
+
+//-------------------------------------------------
+// read_w -
+//-------------------------------------------------
+
+WRITE_LINE_MEMBER( msm58321_device::read_w )
+{
+ if (LOG) logerror("MSM58321 '%s' READ: %u\n", tag(), state);
+
+ m_read = state;
+}
+
+
+//-------------------------------------------------
+// write_w -
+//-------------------------------------------------
+
+WRITE_LINE_MEMBER( msm58321_device::write_w )
+{
+ if (LOG) logerror("MSM58321 '%s' WRITE: %u\n", tag(), state);
+
+ m_write = state;
+}
+
+
+//-------------------------------------------------
+// address_write_w -
+//-------------------------------------------------
+
+WRITE_LINE_MEMBER( msm58321_device::address_write_w )
+{
+ if (LOG) logerror("MSM58321 '%s' ADDRESS WRITE: %u\n", tag(), state);
+
+ m_address_write = state;
+
+ if (m_address_write)
+ {
+ if (LOG) logerror("MSM58321 '%s' Latch Address %01x\n", tag(), m_latch);
+
+ // latch address
+ m_address = m_latch;
+ }
+}
+
+
+//-------------------------------------------------
+// stop_w -
+//-------------------------------------------------
+
+WRITE_LINE_MEMBER( msm58321_device::stop_w )
+{
+ if (LOG) logerror("MSM58321 '%s' STOP: %u\n", tag(), state);
+}
+
+
+//-------------------------------------------------
+// test_w -
+//-------------------------------------------------
+
+WRITE_LINE_MEMBER( msm58321_device::test_w )
+{
+ if (LOG) logerror("MSM58321 '%s' TEST: %u\n", tag(), state);
+}
+
+
+//-------------------------------------------------
+// busy_r -
+//-------------------------------------------------
+
+READ_LINE_MEMBER( msm58321_device::busy_r )
+{
+ return m_busy;
+}
diff --git a/src/emu/msm58321.h b/src/emu/msm58321.h
new file mode 100644
index 00000000000..b03541e2683
--- /dev/null
+++ b/src/emu/msm58321.h
@@ -0,0 +1,140 @@
+/**********************************************************************
+
+ OKI MSM58321RS Real Time Clock/Calendar emulation
+
+ Copyright MESS Team.
+ Visit http://mamedev.org for licensing and usage restrictions.
+
+**********************************************************************
+ _____ _____
+ CS2 1 |* \_/ | 16 Vdd
+ WRITE 2 | | 15 XT
+ READ 3 | | 14 _XT
+ D0 4 | MSM58321 | 13 CS1
+ D1 5 | RTC58321 | 12 TEST
+ D2 6 | | 11 STOP
+ D3 7 | | 10 _BUSY
+ GND 8 |_____________| 9 ADDRESS WRITE
+
+**********************************************************************/
+
+#pragma once
+
+#ifndef __MSM58321__
+#define __MSM58321__
+
+#include "emu.h"
+
+
+
+//**************************************************************************
+// INTERFACE CONFIGURATION MACROS
+//**************************************************************************
+
+#define MCFG_MSM58321_ADD(_tag, _clock, _config) \
+ MCFG_DEVICE_ADD(_tag, MSM58321, _clock) \
+ MCFG_DEVICE_CONFIG(_config)
+
+#define MSM58321_INTERFACE(name) \
+ const msm58321_interface (name) =
+
+
+
+//**************************************************************************
+// TYPE DEFINITIONS
+//**************************************************************************
+
+// ======================> msm58321_interface
+
+struct msm58321_interface
+{
+ devcb_write_line m_out_busy_func;
+};
+
+
+
+// ======================> msm58321_device_config
+
+class msm58321_device_config : public device_config,
+ public msm58321_interface
+{
+ friend class msm58321_device;
+
+ // construction/destruction
+ msm58321_device_config(const machine_config &mconfig, const char *tag, const device_config *owner, UINT32 clock);
+
+public:
+ // allocators
+ static device_config *static_alloc_device_config(const machine_config &mconfig, const char *tag, const device_config *owner, UINT32 clock);
+ virtual device_t *alloc_device(running_machine &machine) const;
+
+protected:
+ // device_config overrides
+ virtual void device_config_complete();
+};
+
+
+
+// ======================> msm58321_device
+
+class msm58321_device : public device_t
+{
+ friend class msm58321_device_config;
+
+ // construction/destruction
+ msm58321_device(running_machine &_machine, const msm58321_device_config &_config);
+
+public:
+ DECLARE_READ8_MEMBER( read );
+ DECLARE_WRITE8_MEMBER( write );
+
+ DECLARE_WRITE_LINE_MEMBER( cs1_w );
+ DECLARE_WRITE_LINE_MEMBER( cs2_w );
+ DECLARE_WRITE_LINE_MEMBER( read_w );
+ DECLARE_WRITE_LINE_MEMBER( write_w );
+ DECLARE_WRITE_LINE_MEMBER( address_write_w );
+ DECLARE_WRITE_LINE_MEMBER( stop_w );
+ DECLARE_WRITE_LINE_MEMBER( test_w );
+ DECLARE_READ_LINE_MEMBER( busy_r );
+
+protected:
+ // device-level overrides
+ virtual void device_start();
+ virtual void device_timer(emu_timer &timer, device_timer_id id, int param, void *ptr);
+
+private:
+ static const device_timer_id TIMER_CLOCK = 0;
+ static const device_timer_id TIMER_BUSY = 1;
+
+ inline int read_counter(int counter);
+ inline void write_counter(int counter, int value);
+ inline void advance_seconds();
+ inline void advance_minutes();
+
+ devcb_resolved_write_line m_out_busy_func;
+
+ int m_cs1; // chip select 1
+ int m_cs2; // chip select 2
+ int m_busy; // busy flag
+ int m_read; // read data
+ int m_write; // write data
+ int m_address_write; // write address
+
+ UINT8 m_reg[13]; // registers
+ UINT8 m_latch; // data latch (not present in real chip)
+ UINT8 m_address; // address latch
+
+ // timers
+ emu_timer *m_clock_timer;
+ emu_timer *m_busy_timer;
+
+ const msm58321_device_config &m_config;
+};
+
+
+// device type definition
+extern const device_type MSM58321;
+
+
+
+#endif