diff options
Diffstat (limited to 'trunk/src/emu/machine/ds1302.c')
-rw-r--r-- | trunk/src/emu/machine/ds1302.c | 215 |
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; +} |