summaryrefslogtreecommitdiffstatshomepage
path: root/trunk/src/emu/machine/ds1302.c
diff options
context:
space:
mode:
Diffstat (limited to 'trunk/src/emu/machine/ds1302.c')
-rw-r--r--trunk/src/emu/machine/ds1302.c215
1 files changed, 215 insertions, 0 deletions
diff --git a/trunk/src/emu/machine/ds1302.c b/trunk/src/emu/machine/ds1302.c
new file mode 100644
index 00000000000..1f6bd0c4d91
--- /dev/null
+++ b/trunk/src/emu/machine/ds1302.c
@@ -0,0 +1,215 @@
+/************************************************************
+
+ DALLAS DS1302
+
+ RTC + BACKUP RAM
+
+
+
+ Emulation by ElSemi
+
+
+ Missing Features:
+ - Burst Mode
+ - Clock programming (useless)
+
+
+
+ 2009-05 Converted to be a device
+
+************************************************************/
+
+
+#include "emu.h"
+#include "ds1302.h"
+#include "devhelpr.h"
+
+
+/***************************************************************************
+ INLINE FUNCTIONS
+***************************************************************************/
+
+INLINE UINT8 convert_to_bcd(int val)
+{
+ return ((val / 10) << 4) | (val % 10);
+}
+
+
+/***************************************************************************
+ IMPLEMENTATION
+***************************************************************************/
+
+//**************************************************************************
+// LIVE DEVICE
+//**************************************************************************
+
+// device type definition
+const device_type DS1302 = &device_creator<ds1302_device>;
+
+//-------------------------------------------------
+// ds1302_device - constructor
+//-------------------------------------------------
+
+ds1302_device::ds1302_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock)
+ : device_t(mconfig, DS1302, "Dallas DS1302 RTC", tag, owner, clock)
+{
+
+}
+
+//-------------------------------------------------
+// device_start - device-specific startup
+//-------------------------------------------------
+
+void ds1302_device::device_start()
+{
+ save_item(NAME(m_shift_in));
+ save_item(NAME(m_shift_out));
+ save_item(NAME(m_icount));
+ save_item(NAME(m_last_clk));
+ save_item(NAME(m_last_cmd));
+ save_item(NAME(m_sram));
+}
+
+
+//-------------------------------------------------
+// device_reset - device-specific reset
+//-------------------------------------------------
+
+void ds1302_device::device_reset()
+{
+ m_shift_in = 0;
+ m_shift_out = 0;
+ m_icount = 0;
+ m_last_clk = 0;
+ m_last_cmd = 0;
+}
+
+
+/*-------------------------------------------------
+ ds1302_dat_w
+-------------------------------------------------*/
+
+WRITE8_DEVICE_HANDLER_TRAMPOLINE(ds1302, ds1302_dat_w)
+{
+ if (data)
+ {
+ m_shift_in |= (1 << m_icount);
+ }
+ else
+ {
+ m_shift_in &= ~(1 << m_icount);
+ }
+}
+
+
+/*-------------------------------------------------
+ ds1302_clk_w
+-------------------------------------------------*/
+
+WRITE8_DEVICE_HANDLER_TRAMPOLINE(ds1302, ds1302_clk_w)
+{
+ if (data != m_last_clk)
+ {
+ if (data) //Rising, shift in command
+ {
+ m_icount++;
+ if(m_icount == 8) //Command start
+ {
+ system_time systime;
+ machine().base_datetime(systime);
+
+ switch(m_shift_in)
+ {
+ case 0x81: //Sec
+ m_shift_out = convert_to_bcd(systime.local_time.second);
+ break;
+
+ case 0x83: //Min
+ m_shift_out = convert_to_bcd(systime.local_time.minute);
+ break;
+
+ case 0x85: //Hour
+ m_shift_out = convert_to_bcd(systime.local_time.hour);
+ break;
+
+ case 0x87: //Day
+ m_shift_out = convert_to_bcd(systime.local_time.mday);
+ break;
+
+ case 0x89: //Month
+ m_shift_out = convert_to_bcd(systime.local_time.month + 1);
+ break;
+
+ case 0x8b: //weekday
+ m_shift_out = convert_to_bcd(systime.local_time.weekday);
+ break;
+
+ case 0x8d: //Year
+ m_shift_out = convert_to_bcd(systime.local_time.year % 100);
+ break;
+
+ default:
+ m_shift_out = 0x0;
+ }
+
+ if(m_shift_in > 0xc0)
+ {
+ m_shift_out = m_sram[(m_shift_in >> 1) & 0x1f];
+ }
+ m_last_cmd = m_shift_in & 0xff;
+ m_icount++;
+ }
+
+ if(m_icount == 17 && !(m_last_cmd & 1))
+ {
+ UINT8 val = (m_shift_in >> 9) & 0xff;
+
+ switch(m_last_cmd)
+ {
+ case 0x80: //Sec
+ break;
+
+ case 0x82: //Min
+ break;
+
+ case 0x84: //Hour
+ break;
+
+ case 0x86: //Day
+ break;
+
+ case 0x88: //Month
+ break;
+
+ case 0x8a: //weekday
+ break;
+
+ case 0x8c: //Year
+ break;
+
+ default:
+ m_shift_out = 0x0;
+ }
+
+ if(m_last_cmd > 0xc0)
+ {
+ m_sram[(m_last_cmd >> 1) & 0x1f] = val;
+ }
+
+
+
+ }
+ }
+ }
+ m_last_clk = data;
+}
+
+
+/*-------------------------------------------------
+ ds1302_read
+-------------------------------------------------*/
+
+READ8_DEVICE_HANDLER_TRAMPOLINE(ds1302, ds1302_read)
+{
+ return (m_shift_out & (1 << (m_icount - 9))) ? 1 : 0;
+}