mirror of
https://github.com/holub/mame
synced 2025-04-23 08:49:55 +03:00
Merge pull request #4105 from hp9k/msm53821_fixes
rtc: add leap year support (nw)
This commit is contained in:
commit
50b026e57f
@ -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)
|
||||
{
|
||||
|
@ -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;
|
||||
};
|
||||
|
||||
|
||||
|
@ -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)
|
||||
|
Loading…
Reference in New Issue
Block a user