diff options
Diffstat (limited to 'src/devices/machine/msm5832.cpp')
-rw-r--r-- | src/devices/machine/msm5832.cpp | 306 |
1 files changed, 306 insertions, 0 deletions
diff --git a/src/devices/machine/msm5832.cpp b/src/devices/machine/msm5832.cpp new file mode 100644 index 00000000000..7bc6fa70bfa --- /dev/null +++ b/src/devices/machine/msm5832.cpp @@ -0,0 +1,306 @@ +// license:BSD-3-Clause +// copyright-holders:Curt Coder +/********************************************************************** + + OKI MSM5832 Real Time Clock/Calendar emulation + +**********************************************************************/ + +/* + + TODO: + + - 12/24 hour + - AM/PM + - leap year + - test input + - reference signal output + +*/ + +#include "msm5832.h" + + +// device type definition +const device_type MSM5832 = &device_creator<msm5832_device>; + + +//************************************************************************** +// MACROS / CONSTANTS +//************************************************************************** + +#define LOG 0 + + +// registers +enum +{ + REGISTER_S1 = 0, + REGISTER_S10, + REGISTER_MI1, + REGISTER_MI10, + REGISTER_H1, + REGISTER_H10, + REGISTER_W, + REGISTER_D1, + REGISTER_D10, + REGISTER_MO1, + REGISTER_MO10, + REGISTER_Y1, + REGISTER_Y10, + REGISTER_REF = 15 +}; + + + +//************************************************************************** +// INLINE HELPERS +//************************************************************************** + +//------------------------------------------------- +// read_counter - +//------------------------------------------------- + +inline int msm5832_device::read_counter(int counter) +{ + return (m_reg[counter + 1] * 10) + m_reg[counter]; +} + + +//------------------------------------------------- +// write_counter - +//------------------------------------------------- + +inline void msm5832_device::write_counter(int counter, int value) +{ + m_reg[counter] = value % 10; + m_reg[counter + 1] = value / 10; +} + + + +//************************************************************************** +// LIVE DEVICE +//************************************************************************** + +//------------------------------------------------- +// msm5832_device - constructor +//------------------------------------------------- + +msm5832_device::msm5832_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock) + : device_t(mconfig, MSM5832, "MSM5832", tag, owner, clock, "msm5832", __FILE__), + device_rtc_interface(mconfig, *this), + m_hold(0), + m_address(0), + m_read(0), + m_write(0), + m_cs(0) +{ + for (int i = 0; i < 13; i++) + m_reg[i] = 0; +} + + +//------------------------------------------------- +// device_start - device-specific startup +//------------------------------------------------- + +void msm5832_device::device_start() +{ + // allocate timers + m_clock_timer = timer_alloc(TIMER_CLOCK); + m_clock_timer->adjust(attotime::from_hz(clock() / 32768), 0, attotime::from_hz(clock() / 32768)); + + // state saving + save_item(NAME(m_reg)); + save_item(NAME(m_hold)); + save_item(NAME(m_address)); + save_item(NAME(m_read)); + save_item(NAME(m_write)); + save_item(NAME(m_cs)); +} + + +//------------------------------------------------- +// device_reset - device-specific reset +//------------------------------------------------- + +void msm5832_device::device_reset() +{ + set_current_time(machine()); +} + + +//------------------------------------------------- +// device_timer - handler timer events +//------------------------------------------------- + +void msm5832_device::device_timer(emu_timer &timer, device_timer_id id, int param, void *ptr) +{ + switch (id) + { + case TIMER_CLOCK: + if (!m_hold) + { + advance_seconds(); + } + break; + } +} + + +//------------------------------------------------- +// rtc_clock_updated - +//------------------------------------------------- + +void msm5832_device::rtc_clock_updated(int year, int month, int day, int day_of_week, int hour, int minute, int second) +{ + write_counter(REGISTER_Y1, year); + write_counter(REGISTER_MO1, month); + write_counter(REGISTER_D1, day); + m_reg[REGISTER_W] = day_of_week-1; + write_counter(REGISTER_H1, hour); + write_counter(REGISTER_MI1, minute); + write_counter(REGISTER_S1, second); +} + + +//------------------------------------------------- +// data_r - +//------------------------------------------------- + +READ8_MEMBER( msm5832_device::data_r ) +{ + UINT8 data = 0; + + if (m_cs && m_read) + { + if (m_address == REGISTER_REF) + { + // TODO reference output + } + else if (m_address <= REGISTER_Y10) + { + data = m_reg[m_address]; + } + else + { + // Otrona Attache CP/M BIOS checks unused registers to detect it + data = 0x0f; + } + } + + if (LOG) logerror("MSM5832 '%s' Register Read %01x: %01x\n", tag(), m_address, data & 0x0f); + + return data & 0x0f; +} + + +//------------------------------------------------- +// data_w - +//------------------------------------------------- + +WRITE8_MEMBER( msm5832_device::data_w ) +{ + if (LOG) logerror("MSM5832 '%s' Register Write %01x: %01x\n", tag(), m_address, data & 0x0f); + + if (m_cs && m_write) + { + if (m_address == REGISTER_REF) + { + // TODO reference output + } + else if (m_address <= REGISTER_Y10) + { + m_reg[m_address] = data & 0x0f; + + set_time(false, read_counter(REGISTER_Y1), read_counter(REGISTER_MO1), read_counter(REGISTER_D1), m_reg[REGISTER_W], + read_counter(REGISTER_H1), read_counter(REGISTER_MI1), read_counter(REGISTER_S1)); + } + } +} + + +//------------------------------------------------- +// address_w - +//------------------------------------------------- + +void msm5832_device::address_w(UINT8 data) +{ + if (LOG) logerror("MSM5832 '%s' Address: %01x\n", tag(), data & 0x0f); + + m_address = data & 0x0f; +} + + +//------------------------------------------------- +// adj_w - +//------------------------------------------------- + +WRITE_LINE_MEMBER( msm5832_device::adj_w ) +{ + if (LOG) logerror("MSM5832 '%s' 30 ADJ: %u\n", tag(), state); + + if (state) + { + adjust_seconds(); + } +} + + +//------------------------------------------------- +// test_w - +//------------------------------------------------- + +WRITE_LINE_MEMBER( msm5832_device::test_w ) +{ + if (LOG) logerror("MSM5832 '%s' TEST: %u\n", tag(), state); +} + + +//------------------------------------------------- +// hold_w - +//------------------------------------------------- + +WRITE_LINE_MEMBER( msm5832_device::hold_w ) +{ + if (LOG) logerror("MSM5832 '%s' HOLD: %u\n", tag(), state); + + m_hold = state; +} + + +//------------------------------------------------- +// read_w - +//------------------------------------------------- + +WRITE_LINE_MEMBER( msm5832_device::read_w ) +{ + if (LOG) logerror("MSM5832 '%s' READ: %u\n", tag(), state); + + m_read = state; +} + + +//------------------------------------------------- +// write_w - +//------------------------------------------------- + +WRITE_LINE_MEMBER( msm5832_device::write_w ) +{ + if (LOG) logerror("MSM5832 '%s' WR: %u\n", tag(), state); + + m_write = state; +} + + +//------------------------------------------------- +// cs_w - +//------------------------------------------------- + +WRITE_LINE_MEMBER( msm5832_device::cs_w ) +{ + if (LOG) logerror("MSM5832 '%s' CS: %u\n", tag(), state); + + m_cs = state; +} |