summaryrefslogtreecommitdiffstatshomepage
path: root/trunk/src/emu/machine/ds2404.c
diff options
context:
space:
mode:
Diffstat (limited to 'trunk/src/emu/machine/ds2404.c')
-rw-r--r--trunk/src/emu/machine/ds2404.c388
1 files changed, 388 insertions, 0 deletions
diff --git a/trunk/src/emu/machine/ds2404.c b/trunk/src/emu/machine/ds2404.c
new file mode 100644
index 00000000000..8ce9c29c900
--- /dev/null
+++ b/trunk/src/emu/machine/ds2404.c
@@ -0,0 +1,388 @@
+/**********************************************************************
+
+ DALLAS DS2404
+
+ RTC + BACKUP RAM
+
+**********************************************************************/
+
+#include "emu.h"
+#include "ds2404.h"
+#include <time.h>
+#include "devhelpr.h"
+
+
+//**************************************************************************
+// LIVE DEVICE
+//**************************************************************************
+
+// device type definition
+const device_type DS2404 = &device_creator<ds2404_device>;
+
+//-------------------------------------------------
+// ds2404_device - constructor
+//-------------------------------------------------
+
+ds2404_device::ds2404_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock)
+ : device_t(mconfig, DS2404, "DS2404", tag, owner, clock),
+ device_nvram_interface(mconfig, *this)
+{
+}
+
+
+//-------------------------------------------------
+// static_set_ref_year - configuration helper
+// to set the reference year
+//-------------------------------------------------
+
+void ds2404_device::static_set_ref_year(device_t &device, UINT32 year)
+{
+ ds2404_device &ds2404 = downcast<ds2404_device &>(device);
+ ds2404.m_ref_year = year;
+}
+
+
+//-------------------------------------------------
+// static_set_ref_month - configuration helper
+// to set the reference month
+//-------------------------------------------------
+
+void ds2404_device::static_set_ref_month(device_t &device, UINT8 month)
+{
+ ds2404_device &ds2404 = downcast<ds2404_device &>(device);
+ ds2404.m_ref_month = month;
+}
+
+
+//-------------------------------------------------
+// static_set_ref_day - configuration helper
+// to set the reference day
+//-------------------------------------------------
+
+void ds2404_device::static_set_ref_day(device_t &device, UINT8 day)
+{
+ ds2404_device &ds2404 = downcast<ds2404_device &>(device);
+ ds2404.m_ref_day = day;
+}
+
+
+//-------------------------------------------------
+// device_start - device-specific startup
+//-------------------------------------------------
+
+void ds2404_device::device_start()
+{
+ struct tm ref_tm;
+
+ memset(&ref_tm, 0, sizeof(ref_tm));
+ ref_tm.tm_year = m_ref_year - 1900;
+ ref_tm.tm_mon = m_ref_month - 1;
+ ref_tm.tm_mday = m_ref_day;
+
+ time_t ref_time = mktime(&ref_tm);
+
+ time_t current_time;
+ time(&current_time);
+ current_time -= ref_time;
+
+ m_rtc[0] = 0x0;
+ m_rtc[1] = (current_time >> 0) & 0xff;
+ m_rtc[2] = (current_time >> 8) & 0xff;
+ m_rtc[3] = (current_time >> 16) & 0xff;
+ m_rtc[4] = (current_time >> 24) & 0xff;
+
+ emu_timer *timer = machine().scheduler().timer_alloc(FUNC(ds2404_tick_callback), (void *)this);
+ timer->adjust(attotime::from_hz(256), 0, attotime::from_hz(256));
+}
+
+
+void ds2404_device::ds2404_rom_cmd(UINT8 cmd)
+{
+ switch(cmd)
+ {
+ case 0xcc: /* Skip ROM */
+ m_state[0] = DS2404_STATE_COMMAND;
+ m_state_ptr = 0;
+ break;
+
+ default:
+ fatalerror("DS2404: Unknown ROM command %02X", cmd);
+ break;
+ }
+}
+
+void ds2404_device::ds2404_cmd(UINT8 cmd)
+{
+ switch(cmd)
+ {
+ case 0x0f: /* Write scratchpad */
+ m_state[0] = DS2404_STATE_ADDRESS1;
+ m_state[1] = DS2404_STATE_ADDRESS2;
+ m_state[2] = DS2404_STATE_INIT_COMMAND;
+ m_state[3] = DS2404_STATE_WRITE_SCRATCHPAD;
+ m_state_ptr = 0;
+ break;
+
+ case 0x55: /* Copy scratchpad */
+ m_state[0] = DS2404_STATE_ADDRESS1;
+ m_state[1] = DS2404_STATE_ADDRESS2;
+ m_state[2] = DS2404_STATE_OFFSET;
+ m_state[3] = DS2404_STATE_INIT_COMMAND;
+ m_state[4] = DS2404_STATE_COPY_SCRATCHPAD;
+ m_state_ptr = 0;
+ break;
+
+ case 0xf0: /* Read memory */
+ m_state[0] = DS2404_STATE_ADDRESS1;
+ m_state[1] = DS2404_STATE_ADDRESS2;
+ m_state[2] = DS2404_STATE_INIT_COMMAND;
+ m_state[3] = DS2404_STATE_READ_MEMORY;
+ m_state_ptr = 0;
+ break;
+
+ default:
+ fatalerror("DS2404: Unknown command %02X", cmd);
+ break;
+ }
+}
+
+UINT8 ds2404_device::ds2404_readmem()
+{
+ if( m_address < 0x200 )
+ {
+ return m_sram[ m_address ];
+ }
+ else if( m_address >= 0x202 && m_address <= 0x206 )
+ {
+ return m_rtc[ m_address - 0x202 ];
+ }
+ return 0;
+}
+
+void ds2404_device::ds2404_writemem(UINT8 value)
+{
+ if( m_address < 0x200 )
+ {
+ m_sram[ m_address ] = value;
+ }
+ else if( m_address >= 0x202 && m_address <= 0x206 )
+ {
+ m_rtc[ m_address - 0x202 ] = value;
+ }
+}
+
+WRITE8_DEVICE_HANDLER_TRAMPOLINE(ds2404, ds2404_1w_reset_w)
+{
+ m_state[0] = DS2404_STATE_IDLE;
+ m_state_ptr = 0;
+}
+
+WRITE8_DEVICE_HANDLER_TRAMPOLINE(ds2404, ds2404_3w_reset_w)
+{
+ m_state[0] = DS2404_STATE_COMMAND;
+ m_state_ptr = 0;
+}
+
+READ8_DEVICE_HANDLER_TRAMPOLINE(ds2404, ds2404_data_r)
+{
+ UINT8 value = 0;
+ switch(m_state[m_state_ptr])
+ {
+ case DS2404_STATE_IDLE:
+ case DS2404_STATE_COMMAND:
+ case DS2404_STATE_ADDRESS1:
+ case DS2404_STATE_ADDRESS2:
+ case DS2404_STATE_OFFSET:
+ case DS2404_STATE_INIT_COMMAND:
+ break;
+
+ case DS2404_STATE_READ_MEMORY:
+ value = ds2404_readmem();
+ break;
+
+ case DS2404_STATE_READ_SCRATCHPAD:
+ if(m_offset < 0x20)
+ {
+ value = m_ram[m_offset];
+ m_offset++;
+ }
+ break;
+
+ case DS2404_STATE_WRITE_SCRATCHPAD:
+ break;
+
+ case DS2404_STATE_COPY_SCRATCHPAD:
+ break;
+ }
+ return value;
+}
+
+WRITE8_DEVICE_HANDLER_TRAMPOLINE(ds2404, ds2404_data_w)
+{
+ switch( m_state[m_state_ptr] )
+ {
+ case DS2404_STATE_IDLE:
+ ds2404_rom_cmd(data & 0xff);
+ break;
+
+ case DS2404_STATE_COMMAND:
+ ds2404_cmd(data & 0xff);
+ break;
+
+ case DS2404_STATE_ADDRESS1:
+ m_a1 = data & 0xff;
+ m_state_ptr++;
+ break;
+
+ case DS2404_STATE_ADDRESS2:
+ m_a2 = data & 0xff;
+ m_state_ptr++;
+ break;
+
+ case DS2404_STATE_OFFSET:
+ m_end_offset = data & 0xff;
+ m_state_ptr++;
+ break;
+
+ case DS2404_STATE_INIT_COMMAND:
+ break;
+
+ case DS2404_STATE_READ_MEMORY:
+ break;
+
+ case DS2404_STATE_READ_SCRATCHPAD:
+ break;
+
+ case DS2404_STATE_WRITE_SCRATCHPAD:
+ if( m_offset < 0x20 )
+ {
+ m_ram[m_offset] = data & 0xff;
+ m_offset++;
+ }
+ else
+ {
+ /* Set OF flag */
+ }
+ break;
+
+ case DS2404_STATE_COPY_SCRATCHPAD:
+ break;
+ }
+
+ if( m_state[m_state_ptr] == DS2404_STATE_INIT_COMMAND )
+ {
+ switch( m_state[m_state_ptr + 1] )
+ {
+ case DS2404_STATE_IDLE:
+ case DS2404_STATE_COMMAND:
+ case DS2404_STATE_ADDRESS1:
+ case DS2404_STATE_ADDRESS2:
+ case DS2404_STATE_OFFSET:
+ case DS2404_STATE_INIT_COMMAND:
+ break;
+
+ case DS2404_STATE_READ_MEMORY:
+ m_address = (m_a2 << 8) | m_a1;
+ m_address -= 1;
+ break;
+
+ case DS2404_STATE_WRITE_SCRATCHPAD:
+ m_address = (m_a2 << 8) | m_a1;
+ m_offset = m_address & 0x1f;
+ break;
+
+ case DS2404_STATE_READ_SCRATCHPAD:
+ m_address = (m_a2 << 8) | m_a1;
+ m_offset = m_address & 0x1f;
+ break;
+
+ case DS2404_STATE_COPY_SCRATCHPAD:
+ m_address = (m_a2 << 8) | m_a1;
+
+ for(int i = 0; i <= m_end_offset; i++)
+ {
+ ds2404_writemem(m_ram[i]);
+ m_address++;
+ }
+ break;
+ }
+ m_state_ptr++;
+ }
+}
+
+WRITE8_DEVICE_HANDLER_TRAMPOLINE(ds2404, ds2404_clk_w)
+{
+ switch( m_state[m_state_ptr] )
+ {
+ case DS2404_STATE_IDLE:
+ case DS2404_STATE_COMMAND:
+ case DS2404_STATE_ADDRESS1:
+ case DS2404_STATE_ADDRESS2:
+ case DS2404_STATE_OFFSET:
+ case DS2404_STATE_INIT_COMMAND:
+ break;
+
+ case DS2404_STATE_READ_MEMORY:
+ m_address++;
+ break;
+
+ case DS2404_STATE_READ_SCRATCHPAD:
+ break;
+
+ case DS2404_STATE_WRITE_SCRATCHPAD:
+ break;
+
+ case DS2404_STATE_COPY_SCRATCHPAD:
+ break;
+ }
+}
+
+TIMER_CALLBACK( ds2404_device::ds2404_tick_callback )
+{
+ reinterpret_cast<ds2404_device*>(ptr)->ds2404_tick();
+}
+
+void ds2404_device::ds2404_tick()
+{
+ for(int i = 0; i < 5; i++)
+ {
+ m_rtc[ i ]++;
+ if(m_rtc[ i ] != 0)
+ {
+ break;
+ }
+ }
+}
+
+
+//-------------------------------------------------
+// nvram_default - called to initialize NVRAM to
+// its default state
+//-------------------------------------------------
+
+void ds2404_device::nvram_default()
+{
+ memset(m_sram, 0, sizeof(m_sram));
+}
+
+
+//-------------------------------------------------
+// nvram_read - called to read NVRAM from the
+// .nv file
+//-------------------------------------------------
+
+void ds2404_device::nvram_read(emu_file &file)
+{
+ file.read(m_sram, sizeof(m_sram));
+}
+
+
+//-------------------------------------------------
+// nvram_write - called to write NVRAM to the
+// .nv file
+//-------------------------------------------------
+
+void ds2404_device::nvram_write(emu_file &file)
+{
+ file.write(m_sram, sizeof(m_sram));
+}