From 7b48d52e94d56355404d7e2e26e2bf648e3525fb Mon Sep 17 00:00:00 2001 From: Sven Schnelle Date: Wed, 10 Oct 2018 14:17:48 +0200 Subject: rtc: add leap year support (nw) msm53821: - add standard register support - use std::array - fix several counter to behave like a real MSM53821 --- src/devices/machine/msm58321.cpp | 108 ++++++++++++++++++++++++--------------- src/devices/machine/msm58321.h | 13 +++-- src/emu/dirtc.cpp | 9 ++-- 3 files changed, 82 insertions(+), 48 deletions(-) diff --git a/src/devices/machine/msm58321.cpp b/src/devices/machine/msm58321.cpp index 97bd2a55f09..550645b5255 100644 --- a/src/devices/machine/msm58321.cpp +++ b/src/devices/machine/msm58321.cpp @@ -1,5 +1,5 @@ // license:BSD-3-Clause -// copyright-holders:Curt Coder +// copyright-holders:Curt Coder,Sven Schnelle /********************************************************************** OKI MSM58321RS Real Time Clock/Calendar emulation @@ -10,9 +10,7 @@ TODO: - - leap year - - test - - reference registers + - non gregorian leap year */ @@ -105,21 +103,13 @@ inline int msm58321_device::read_counter(int counter) { data += (h10 & 3) * 10; } + else if (h10 & H10_PM) + { + data += 12 + (h10 & 1) * 10; + } else { data += (h10 & 1) * 10; - - if (h10 & H10_PM) - { - if (data != 12) - { - data += 12; - } - } - else if (data == 12) - { - data = 0; - } } } else @@ -139,8 +129,7 @@ inline void msm58321_device::write_counter(int address, int data) { int flag = 0; - switch (address) - { + switch (address) { case REGISTER_H1: flag = m_reg[REGISTER_H10] & H10_24; if (!flag) @@ -151,10 +140,8 @@ inline void msm58321_device::write_counter(int address, int data) flag = H10_PM; } - if (data == 0) - { + if ((m_reg[REGISTER_H10] & H10_PM) && data == 0) data = 12; - } } break; @@ -200,9 +187,9 @@ msm58321_device::msm58321_device(const machine_config &mconfig, const char *tag, m_stop(0), m_test(0), m_cs1(0), - m_address(0xf) + m_address(0xf), + m_reg{} { - memset(m_reg, 0x00, sizeof(m_reg)); } @@ -221,12 +208,16 @@ void msm58321_device::device_start() // allocate timers m_clock_timer = timer_alloc(TIMER_CLOCK); - m_clock_timer->adjust(clocks_to_attotime(32768), 0, clocks_to_attotime(32768)); + m_clock_timer->adjust(clocks_to_attotime(32768/1024), 0, clocks_to_attotime(32768/1024)); // busy signal active period is approximately 427 µs m_busy_timer = timer_alloc(TIMER_BUSY); m_busy_timer->adjust(clocks_to_attotime(32768 - 14), 0, clocks_to_attotime(32768)); + // standard signal active period is approximately 122 µs + m_standard_timer = timer_alloc(TIMER_STANDARD); + m_standard_timer->adjust(clocks_to_attotime(32768-4), 0, clocks_to_attotime(32768)); + // state saving save_item(NAME(m_cs2)); save_item(NAME(m_write)); @@ -258,12 +249,29 @@ void msm58321_device::device_timer(emu_timer &timer, device_timer_id id, int par switch (id) { case TIMER_CLOCK: - if (!m_stop) - advance_seconds(); - if (!m_busy) + + if (m_khz_ctr & 1) { - m_busy = 1; - m_busy_handler(m_busy); + m_reg[REGISTER_REF0] |= 1; + m_reg[REGISTER_REF1] |= 1; + } else { + m_reg[REGISTER_REF0] &= ~1; + m_reg[REGISTER_REF1] &= ~1; + } + + if (++m_khz_ctr >= 1024) + { + m_khz_ctr = 0; + if (!m_stop) + { + advance_seconds(); + } + + if (!m_busy) + { + m_busy = 1; + m_busy_handler(m_busy); + } } break; @@ -274,9 +282,29 @@ void msm58321_device::device_timer(emu_timer &timer, device_timer_id id, int par m_busy_handler(m_busy); } break; + case TIMER_STANDARD: + m_reg[REGISTER_REF0] = 0x0e; + m_reg[REGISTER_REF1] = 0x0e; + break; } } +void msm58321_device::update_standard() +{ + uint8_t reg = 0; + + if (m_reg[REGISTER_S1] == 0) + reg |= 1 << 1; + + if (m_reg[REGISTER_MI1] == 0) + reg |= 1 << 2; + + if (m_reg[REGISTER_H1] == 0) + reg |= 1 << 3; + + m_reg[REGISTER_REF0] = (reg ^ 0x0e) | (m_khz_ctr & 1); + m_reg[REGISTER_REF1] = m_reg[REGISTER_REF0]; +} //------------------------------------------------- // rtc_clock_updated - @@ -291,7 +319,7 @@ void msm58321_device::rtc_clock_updated(int year, int month, int day, int day_of write_counter(REGISTER_H1, hour); write_counter(REGISTER_MI1, minute); write_counter(REGISTER_S1, second); - + update_standard(); update_output(); } @@ -319,7 +347,7 @@ void msm58321_device::nvram_default() void msm58321_device::nvram_read(emu_file &file) { - file.read(m_reg, sizeof(m_reg)); + file.read(m_reg.data(), m_reg.size()); clock_updated(); } @@ -332,7 +360,7 @@ void msm58321_device::nvram_read(emu_file &file) void msm58321_device::nvram_write(emu_file &file) { - file.write(m_reg, sizeof(m_reg)); + file.write(m_reg.data(), m_reg.size()); } //------------------------------------------------- @@ -350,13 +378,9 @@ void msm58321_device::update_output() case REGISTER_RESET: data = 0; break; - - case REGISTER_REF0: - case REGISTER_REF1: - // TODO: output reference values - data = 0; + case REGISTER_W: + data = m_reg[m_address] - 1; break; - default: data = m_reg[m_address]; break; @@ -434,15 +458,17 @@ void msm58321_device::update_input() default: LOG("MSM58321 Register Write %s (%01x): %01x\n", reg_name(m_address), m_address, data); - + m_khz_ctr = 0; switch (m_address) { case REGISTER_S10: case REGISTER_MI10: - case REGISTER_W: + m_reg[m_address] = data & 7; break; - + case REGISTER_W: + m_reg[m_address] = (data & 7) + 1; + break; case REGISTER_H10: if (data & H10_24) { diff --git a/src/devices/machine/msm58321.h b/src/devices/machine/msm58321.h index 00f5a524322..1842b4f2036 100644 --- a/src/devices/machine/msm58321.h +++ b/src/devices/machine/msm58321.h @@ -114,14 +114,16 @@ protected: virtual void nvram_default() override; virtual void nvram_read(emu_file &file) override; virtual void nvram_write(emu_file &file) override; + virtual bool rtc_feature_leap_year() const override { return true; } private: - static const device_timer_id TIMER_CLOCK = 0; - static const device_timer_id TIMER_BUSY = 1; + static constexpr device_timer_id TIMER_CLOCK = 0; + static constexpr device_timer_id TIMER_BUSY = 1; + static constexpr device_timer_id TIMER_STANDARD = 2; void update_input(); void update_output(); - + void update_standard(); inline int read_counter(int counter); inline void write_counter(int counter, int value); @@ -151,11 +153,14 @@ private: int m_cs1; // chip select 1 uint8_t m_address; // address latch - uint8_t m_reg[13]; // registers + std::array m_reg; // registers // timers emu_timer *m_clock_timer; emu_timer *m_busy_timer; + emu_timer *m_standard_timer; + + int m_khz_ctr; }; diff --git a/src/emu/dirtc.cpp b/src/emu/dirtc.cpp index 4243622822b..0d5442fe6c2 100644 --- a/src/emu/dirtc.cpp +++ b/src/emu/dirtc.cpp @@ -195,10 +195,13 @@ void device_rtc_interface::advance_days() m_register[RTC_DAY_OF_WEEK] = 1; } - if (m_register[RTC_DAY] > DAYS_PER_MONTH[m_register[RTC_MONTH] - 1]) + if (m_register[RTC_MONTH] > 0 && m_register[RTC_DAY] > DAYS_PER_MONTH[m_register[RTC_MONTH] - 1]) { - m_register[RTC_DAY] = 1; - m_register[RTC_MONTH]++; + if (m_register[RTC_MONTH] != 2 || m_register[RTC_DAY] != 29 || !rtc_feature_leap_year() || + (m_register[RTC_YEAR] % 4) != 0) { + m_register[RTC_DAY] = 1; + m_register[RTC_MONTH]++; + } } if (m_register[RTC_MONTH] == 13) -- cgit v1.2.3