Merge pull request #4105 from hp9k/msm53821_fixes

rtc: add leap year support (nw)
This commit is contained in:
R. Belmont 2018-10-10 13:41:31 -04:00 committed by GitHub
commit 50b026e57f
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 82 additions and 48 deletions

View File

@ -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)
{

View File

@ -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<uint8_t, 16> m_reg; // registers
// timers
emu_timer *m_clock_timer;
emu_timer *m_busy_timer;
emu_timer *m_standard_timer;
int m_khz_ctr;
};

View File

@ -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)