summaryrefslogtreecommitdiffstatshomepage
path: root/src/devices/machine/ds1315.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/devices/machine/ds1315.cpp')
-rw-r--r--src/devices/machine/ds1315.cpp277
1 files changed, 277 insertions, 0 deletions
diff --git a/src/devices/machine/ds1315.cpp b/src/devices/machine/ds1315.cpp
new file mode 100644
index 00000000000..8470aaaaf9c
--- /dev/null
+++ b/src/devices/machine/ds1315.cpp
@@ -0,0 +1,277 @@
+// license:BSD-3-Clause
+// copyright-holders:Tim Lindner
+/*****************************************************************************************
+
+ ds1315.c
+
+ Dallas Semiconductor's Phantom Time Chip DS1315.
+ NOTE: writes are decoded, but the host's time will always be returned when asked.
+
+ April 2015: chip enable / chip reset / phantom writes by Karl-Ludwig Deisenhofer
+
+ November 2001: implementation by Tim Lindner
+
+ HOW DOES IT WORK?
+
+ READS: pattern recognition (64 bits in correct order). When RTC finally enables
+ 64 bits of data can be read. Chance of accidential pattern recognition is minimal.
+
+ WRITES: two different locations (bits 0 and 1) are used to transfer data to the
+ DS1315. 64 bit with time/date info are transmitted directly after recognition
+ of the magic 64 bit pattern (see read above).
+ **************************************************************************************/
+
+#include "ds1315.h"
+#include "coreutil.h"
+
+
+const device_type DS1315 = &device_creator<ds1315_device>;
+
+ds1315_device::ds1315_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock)
+ : device_t(mconfig, DS1315, "Dallas Semiconductor DS1315", tag, owner, clock, "ds1315", __FILE__)
+{
+}
+
+//-------------------------------------------------
+// device_config_complete - perform any
+// operations now that the configuration is
+// complete
+//-------------------------------------------------
+
+void ds1315_device::device_config_complete()
+{
+}
+
+//-------------------------------------------------
+// device_start - device-specific startup
+//-------------------------------------------------
+
+void ds1315_device::device_start()
+{
+ save_item(NAME(m_count));
+ save_item(NAME(m_mode));
+ save_item(NAME(m_raw_data));
+}
+
+
+//-------------------------------------------------
+// device_reset - device-specific reset
+//-------------------------------------------------
+
+void ds1315_device::device_reset()
+{
+ chip_reset();
+}
+
+
+
+/***************************************************************************
+ LOCAL VARIABLES
+***************************************************************************/
+
+static const UINT8 ds1315_pattern[] =
+{
+ 1, 0, 1, 0, 0, 0, 1, 1,
+ 0, 1, 0, 1, 1, 1, 0, 0,
+ 1, 1, 0, 0, 0, 1, 0, 1,
+ 0, 0, 1, 1, 1, 0, 1, 0,
+ 1, 0, 1, 0, 0, 0, 1, 1,
+ 0, 1, 0, 1, 1, 1, 0, 0,
+ 1, 1, 0, 0, 0, 1, 0, 1,
+ 0, 0, 1, 1, 1, 0, 1, 0
+};
+
+
+/***************************************************************************
+ IMPLEMENTATION
+***************************************************************************/
+
+/*-------------------------------------------------
+ read_0 (actual data)
+ -------------------------------------------------*/
+
+READ8_MEMBER( ds1315_device::read_0 )
+{
+ if (ds1315_pattern[m_count++] == 0)
+ {
+ if (m_count == 64)
+ {
+ /* entire pattern matched */
+ m_count = 0;
+ m_mode = DS_CALENDAR_IO;
+ fill_raw_data();
+ }
+
+ return 0;
+ }
+
+ m_count = 0;
+ m_mode = DS_SEEK_MATCHING;
+ return 0;
+}
+
+
+/*-------------------------------------------------
+ read_1 (actual data)
+-------------------------------------------------*/
+
+READ8_MEMBER( ds1315_device::read_1 )
+{
+ if (ds1315_pattern[m_count++] == 1)
+ {
+ m_count %= 64;
+ return 0;
+ }
+
+ m_count = 0;
+ m_mode = DS_SEEK_MATCHING;
+ return 0;
+}
+
+
+/*-------------------------------------------------
+ read_data
+-------------------------------------------------*/
+
+READ8_MEMBER( ds1315_device::read_data )
+{
+ UINT8 result;
+
+ if (m_mode == DS_CALENDAR_IO)
+ {
+ result = m_raw_data[m_count++];
+
+ if (m_count == 64)
+ {
+ m_mode = DS_SEEK_MATCHING;
+ m_count = 0;
+ }
+
+ return result;
+ }
+
+ m_count = 0;
+ return 0;
+}
+
+
+/*-------------------------------------------------
+ fill_raw_data
+-------------------------------------------------*/
+
+void ds1315_device::fill_raw_data()
+{
+ /* This routine calls a standard 'C' library routine to get the current
+ date and time and then fill in the raw data struct.
+ */
+
+ system_time systime;
+ int raw[8], i, j;
+
+ /* get the current date/time from the core */
+ machine().current_datetime(systime);
+
+ raw[0] = 0; /* tenths and hundreths of seconds are always zero */
+ raw[1] = dec_2_bcd(systime.local_time.second);
+ raw[2] = dec_2_bcd(systime.local_time.minute);
+ raw[3] = dec_2_bcd(systime.local_time.hour);
+
+ raw[4] = dec_2_bcd((systime.local_time.weekday != 0) ? systime.local_time.weekday : 7);
+ raw[5] = dec_2_bcd(systime.local_time.mday);
+ raw[6] = dec_2_bcd(systime.local_time.month + 1);
+ raw[7] = dec_2_bcd(systime.local_time.year - 1900); /* Epoch is 1900 */
+
+ /* Ok now we have the raw bcd bytes. Now we need to push them into our bit array */
+
+ for (i = 0; i < 64; i++)
+ {
+ j = i / 8;
+ m_raw_data[i] = (raw[j] & 0x0001);
+ raw[j] = raw[j] >> 1;
+ }
+}
+
+
+
+
+/*-------------------------------------------------
+write_data
+-------------------------------------------------*/
+
+READ8_MEMBER(ds1315_device::write_data)
+{
+ static int write_count;
+ if (write_count >= 64)
+ write_count = 0;
+
+ if (m_mode == DS_CALENDAR_IO)
+ {
+ m_raw_data[write_count++] = offset & 0x01;
+
+ if (write_count == 64)
+ {
+ write_count = 0;
+
+ m_mode = DS_SEEK_MATCHING;
+ m_count = 0;
+ input_raw_data();
+ }
+ }
+ return 0; // ignore
+}
+
+/*-------------------------------------------------
+ ds1315_input_raw_data
+
+ Routine is called when new date and time has
+ been written to the clock chip. Currently we
+ ignore setting the date and time in the clock
+ chip.
+-------------------------------------------------*/
+
+void ds1315_device::input_raw_data()
+{
+ int raw[8], i, j=0;
+ raw[0] = raw[1] = raw[2] = raw[3] = raw[4] = raw[5] = raw[6] = raw[7] = 0;
+ UINT8 flag = 1;
+
+ for (i = 0; i < 64; i++)
+ {
+ j = i / 8;
+ if ((i % 8) == 0)
+ flag = 1;
+
+ if (m_raw_data[i] & 1)
+ raw[j] |= flag;
+ flag <<= 1;
+ }
+ raw[0] = bcd_2_dec(raw[0]); // hundreds of seconds
+ raw[1] = bcd_2_dec(raw[1]); // seconds (often set to zero)
+ raw[2] = bcd_2_dec(raw[2]); // minute
+ raw[3] = bcd_2_dec(raw[3]); // hour
+
+ raw[4] = bcd_2_dec(raw[4]); // weekday (10 for Friday ?!)
+ raw[5] = bcd_2_dec(raw[5]); // mday
+ raw[6] = bcd_2_dec(raw[6]); // month
+ raw[7] = bcd_2_dec(raw[7]); // year (two digits)
+
+ printf("\nDS1315 RTC INPUT (WILL BE IGNORED) mm/dd/yy hh:mm:ss - %02d/%02d/%02d %02d/%02d/%02d",
+ raw[6], raw[5], raw[7], raw[3], raw[2], raw[1]
+ );
+}
+
+/*-------------------------------------------------
+ query and reset chip status
+ -------------------------------------------------*/
+bool ds1315_device::chip_enable()
+{
+ return (m_mode == DS_CALENDAR_IO);
+}
+
+// Set a defined state (important for pattern detection)
+void ds1315_device::chip_reset()
+{
+ memset(m_raw_data, 0, sizeof(m_raw_data));
+ m_count = 0;
+ m_mode = DS_SEEK_MATCHING;
+}