summaryrefslogtreecommitdiffstatshomepage
path: root/trunk/src/emu/machine/msm6242.c
diff options
context:
space:
mode:
Diffstat (limited to 'trunk/src/emu/machine/msm6242.c')
-rw-r--r--trunk/src/emu/machine/msm6242.c313
1 files changed, 313 insertions, 0 deletions
diff --git a/trunk/src/emu/machine/msm6242.c b/trunk/src/emu/machine/msm6242.c
new file mode 100644
index 00000000000..25e294e5e39
--- /dev/null
+++ b/trunk/src/emu/machine/msm6242.c
@@ -0,0 +1,313 @@
+/***************************************************************************
+
+ MSM6242 Real Time Clock
+
+ TODO:
+ - HOLD mechanism
+ - IRQ ACK
+ - why skns tries to read uninitialized registers?
+
+***************************************************************************/
+
+#include "emu.h"
+#include "machine/msm6242.h"
+#include "machine/devhelpr.h"
+
+
+enum
+{
+ MSM6242_REG_S1 = 0,
+ MSM6242_REG_S10,
+ MSM6242_REG_MI1,
+ MSM6242_REG_MI10,
+ MSM6242_REG_H1,
+ MSM6242_REG_H10,
+ MSM6242_REG_D1,
+ MSM6242_REG_D10,
+ MSM6242_REG_MO1,
+ MSM6242_REG_MO10,
+ MSM6242_REG_Y1,
+ MSM6242_REG_Y10,
+ MSM6242_REG_W,
+ MSM6242_REG_CD,
+ MSM6242_REG_CE,
+ MSM6242_REG_CF
+};
+
+//**************************************************************************
+// GLOBAL VARIABLES
+//**************************************************************************
+
+// device type definition
+const device_type msm6242 = &device_creator<msm6242_device>;
+
+
+//**************************************************************************
+// LIVE DEVICE
+//**************************************************************************
+
+//-------------------------------------------------
+// xxx_device - constructor
+//-------------------------------------------------
+
+msm6242_device::msm6242_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock)
+ : device_t(mconfig, msm6242, "msm6242", tag, owner, clock)
+{
+
+}
+
+void msm6242_device::rtc_timer_callback()
+{
+ static const UINT8 dpm[12] = { 0x31, 0x28, 0x31, 0x30, 0x31, 0x30, 0x31, 0x31, 0x30, 0x31, 0x30, 0x31 };
+ int dpm_count;
+
+ m_tick++;
+
+ if(m_irq_flag == 1 && m_irq_type == 0 && ((m_tick % 0x200) == 0)) // 1/64 of second
+ {
+ if ( !m_out_int_func.isnull() )
+ m_out_int_func( ASSERT_LINE );
+ }
+
+ if(m_tick & 0x8000) // 32,768 KHz == 0x8000 ticks
+ {
+ m_tick = 0;
+ m_rtc.sec++;
+
+ if(m_irq_flag == 1 && m_irq_type == 1) // 1 second clock
+ if ( !m_out_int_func.isnull() )
+ m_out_int_func(ASSERT_LINE);
+
+ if(m_rtc.sec >= 60)
+ {
+ m_rtc.min++; m_rtc.sec = 0;
+ if(m_irq_flag == 1 && m_irq_type == 2) // 1 minute clock
+ if ( !m_out_int_func.isnull() )
+ m_out_int_func(ASSERT_LINE);
+ }
+ if(m_rtc.min >= 60)
+ {
+ m_rtc.hour++; m_rtc.min = 0;
+ if(m_irq_flag == 1 && m_irq_type == 3) // 1 hour clock
+ if ( !m_out_int_func.isnull() )
+ m_out_int_func(ASSERT_LINE);
+ }
+ if(m_rtc.hour >= 24) { m_rtc.day++; m_rtc.wday++; m_rtc.hour = 0; }
+ if(m_rtc.wday >= 6) { m_rtc.wday = 1; }
+
+ /* TODO: crude leap year support */
+ dpm_count = (m_rtc.month)-1;
+
+ if(((m_rtc.year % 4) == 0) && m_rtc.month == 2)
+ {
+ if((m_rtc.day) >= dpm[dpm_count]+1+1)
+ { m_rtc.month++; m_rtc.day = 0x01; }
+ }
+ else if(m_rtc.day >= dpm[dpm_count]+1) { m_rtc.month++; m_rtc.day = 0x01; }
+ if(m_rtc.month >= 0x13) { m_rtc.year++; m_rtc.month = 1; }
+ if(m_rtc.year >= 100) { m_rtc.year = 0; } //1900-1999 possible timeframe
+ }
+}
+
+TIMER_CALLBACK( msm6242_device::rtc_inc_callback )
+{
+ reinterpret_cast<msm6242_device *>(ptr)->rtc_timer_callback();
+}
+
+//-------------------------------------------------
+// device_validity_check - perform validity checks
+// on this device
+//-------------------------------------------------
+
+void msm6242_device::device_validity_check(validity_checker &valid) const
+{
+}
+
+//-------------------------------------------------
+// device_start - device-specific startup
+//-------------------------------------------------
+
+void msm6242_device::device_start()
+{
+ m_out_int_func.resolve( m_out_int_cb, *this );
+
+ /* let's call the timer callback every second */
+ machine().scheduler().timer_pulse(attotime::from_hz(clock()), FUNC(rtc_inc_callback), 0, (void *)this);
+
+ system_time systime;
+ machine().base_datetime(systime);
+
+ m_rtc.day = (systime.local_time.mday);
+ m_rtc.month = (systime.local_time.month+1);
+ m_rtc.wday = (systime.local_time.weekday);
+ m_rtc.year = (systime.local_time.year % 100);
+ m_rtc.hour = (systime.local_time.hour);
+ m_rtc.min = (systime.local_time.minute);
+ m_rtc.sec = (systime.local_time.second);
+ m_tick = 0;
+ m_irq_flag = 0;
+ m_irq_type = 0;
+
+ /* TODO: skns writes 0x4 to D then expects E == 6 and F == 4, perhaps those are actually saved in the RTC CMOS? */
+ m_reg[0] = 0;
+ m_reg[1] = 0x6;
+ m_reg[2] = 0x4;
+}
+
+
+//-------------------------------------------------
+// device_reset - device-specific reset
+//-------------------------------------------------
+
+void msm6242_device::device_reset()
+{
+ if ( !m_out_int_func.isnull() )
+ m_out_int_func( CLEAR_LINE );
+}
+
+
+//-------------------------------------------------
+// device_config_complete - perform any
+// operations now that the configuration is
+// complete
+//-------------------------------------------------
+
+void msm6242_device::device_config_complete()
+{
+ const msm6242_interface *intf = reinterpret_cast<const msm6242_interface *>(static_config());
+
+ if ( intf != NULL )
+ {
+ *static_cast<msm6242_interface *>(this) = *intf;
+ }
+ else
+ {
+ memset(&m_out_int_cb, 0, sizeof(m_out_int_cb));
+ }
+}
+
+//**************************************************************************
+// READ/WRITE HANDLERS
+//**************************************************************************
+
+READ8_MEMBER( msm6242_device::read )
+{
+ rtc_regs_t cur_time;
+
+ //cur_time = (m_reg[0] & 1) ? m_hold : m_rtc;
+
+ cur_time = m_rtc;
+
+ switch(offset)
+ {
+ case MSM6242_REG_S1: return (cur_time.sec % 10) & 0xf;
+ case MSM6242_REG_S10: return (cur_time.sec / 10) & 0xf;
+ case MSM6242_REG_MI1: return (cur_time.min % 10) & 0xf;
+ case MSM6242_REG_MI10: return (cur_time.min / 10) & 0xf;
+ case MSM6242_REG_H1:
+ case MSM6242_REG_H10:
+ {
+ int hour = cur_time.hour;
+ int pm = 0;
+
+ /* check for 12/24 hour mode */
+ if ((m_reg[2] & 0x04) == 0) /* 12 hour mode? */
+ {
+ if (hour >= 12)
+ pm = 1;
+
+ hour %= 12;
+
+ if ( hour == 0 )
+ hour = 12;
+ }
+
+ if ( offset == MSM6242_REG_H1 )
+ return hour % 10;
+
+ return (hour / 10) | (pm <<2);
+ }
+
+ case MSM6242_REG_D1: return (cur_time.day % 10) & 0xf;
+ case MSM6242_REG_D10: return (cur_time.day / 10) & 0xf;
+ case MSM6242_REG_MO1: return (cur_time .month % 10) & 0xf;
+ case MSM6242_REG_MO10: return (cur_time.month / 10) & 0xf;
+ case MSM6242_REG_Y1: return (cur_time.year % 10) & 0xf;
+ case MSM6242_REG_Y10: return ((cur_time.year / 10) % 10) & 0xf;
+ case MSM6242_REG_W: return cur_time.wday;
+ case MSM6242_REG_CD: return m_reg[0];
+ case MSM6242_REG_CE: return m_reg[1];
+ case MSM6242_REG_CF: return m_reg[2];
+ }
+
+ logerror("%s: MSM6242 unmapped offset %02x read\n", machine().describe_context(), offset);
+ return 0;
+}
+
+WRITE8_MEMBER( msm6242_device::write )
+{
+ switch(offset)
+ {
+ case MSM6242_REG_CD:
+ {
+ m_reg[0] = data & 0x0f;
+
+ #if 0
+ if (data & 1) /* was Hold set? */
+ {
+ m_hold.day = m_rtc.day;
+ m_hold.month = m_rtc.month;
+ m_hold.hour = m_rtc.hour;
+ m_hold.day = m_rtc.day;
+ m_hold.month = m_rtc.month;
+ m_hold.year = m_rtc.year;
+ m_hold.wday = m_rtc.wday;
+ }
+ #endif
+
+ return;
+ }
+
+ case MSM6242_REG_CE:
+ m_reg[1] = data & 0x0f;
+ if((data & 3) == 0) // MASK & STD = 0
+ {
+ m_irq_flag = 1;
+ m_irq_type = (data & 0xc) >> 2;
+ //m_std_timer->adjust(attotime::from_msec(timer_param[(data & 0xc) >> 2]), 0, attotime::from_msec(timer_param[(data & 0xc) >> 2]));
+ }
+ else
+ {
+ m_irq_flag = 0;
+ if ( !m_out_int_func.isnull() )
+ m_out_int_func( CLEAR_LINE );
+ }
+
+ return;
+
+ case MSM6242_REG_CF:
+ {
+ /* the 12/24 mode bit can only be changed while REST is 1 */
+ if ((data ^ m_reg[2]) & 0x04)
+ {
+ m_reg[2] = (m_reg[2] & 0x04) | (data & ~0x04);
+
+ if (m_reg[2] & 1)
+ m_reg[2] = (m_reg[2] & ~0x04) | (data & 0x04);
+ }
+ else
+ {
+ m_reg[2] = data & 0x0f;
+ }
+ return;
+ }
+ }
+
+ logerror("%s: MSM6242 unmapped offset %02x written with %02x\n", machine().describe_context(), offset, data);
+}
+
+
+
+
+
+