mirror of
https://github.com/holub/mame
synced 2025-07-01 16:19:38 +03:00
rtc: add leap year support (nw)
msm53821: - add standard register support - use std::array - fix several counter to behave like a real MSM53821
This commit is contained in:
parent
4c36a851f0
commit
7b48d52e94
@ -1,5 +1,5 @@
|
|||||||
// license:BSD-3-Clause
|
// license:BSD-3-Clause
|
||||||
// copyright-holders:Curt Coder
|
// copyright-holders:Curt Coder,Sven Schnelle
|
||||||
/**********************************************************************
|
/**********************************************************************
|
||||||
|
|
||||||
OKI MSM58321RS Real Time Clock/Calendar emulation
|
OKI MSM58321RS Real Time Clock/Calendar emulation
|
||||||
@ -10,9 +10,7 @@
|
|||||||
|
|
||||||
TODO:
|
TODO:
|
||||||
|
|
||||||
- leap year
|
- non gregorian leap year
|
||||||
- test
|
|
||||||
- reference registers
|
|
||||||
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
@ -105,21 +103,13 @@ inline int msm58321_device::read_counter(int counter)
|
|||||||
{
|
{
|
||||||
data += (h10 & 3) * 10;
|
data += (h10 & 3) * 10;
|
||||||
}
|
}
|
||||||
|
else if (h10 & H10_PM)
|
||||||
|
{
|
||||||
|
data += 12 + (h10 & 1) * 10;
|
||||||
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
data += (h10 & 1) * 10;
|
data += (h10 & 1) * 10;
|
||||||
|
|
||||||
if (h10 & H10_PM)
|
|
||||||
{
|
|
||||||
if (data != 12)
|
|
||||||
{
|
|
||||||
data += 12;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else if (data == 12)
|
|
||||||
{
|
|
||||||
data = 0;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
@ -139,8 +129,7 @@ inline void msm58321_device::write_counter(int address, int data)
|
|||||||
{
|
{
|
||||||
int flag = 0;
|
int flag = 0;
|
||||||
|
|
||||||
switch (address)
|
switch (address) {
|
||||||
{
|
|
||||||
case REGISTER_H1:
|
case REGISTER_H1:
|
||||||
flag = m_reg[REGISTER_H10] & H10_24;
|
flag = m_reg[REGISTER_H10] & H10_24;
|
||||||
if (!flag)
|
if (!flag)
|
||||||
@ -151,11 +140,9 @@ inline void msm58321_device::write_counter(int address, int data)
|
|||||||
flag = H10_PM;
|
flag = H10_PM;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (data == 0)
|
if ((m_reg[REGISTER_H10] & H10_PM) && data == 0)
|
||||||
{
|
|
||||||
data = 12;
|
data = 12;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case REGISTER_D1:
|
case REGISTER_D1:
|
||||||
@ -200,9 +187,9 @@ msm58321_device::msm58321_device(const machine_config &mconfig, const char *tag,
|
|||||||
m_stop(0),
|
m_stop(0),
|
||||||
m_test(0),
|
m_test(0),
|
||||||
m_cs1(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
|
// allocate timers
|
||||||
m_clock_timer = timer_alloc(TIMER_CLOCK);
|
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
|
// busy signal active period is approximately 427 µs
|
||||||
m_busy_timer = timer_alloc(TIMER_BUSY);
|
m_busy_timer = timer_alloc(TIMER_BUSY);
|
||||||
m_busy_timer->adjust(clocks_to_attotime(32768 - 14), 0, clocks_to_attotime(32768));
|
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
|
// state saving
|
||||||
save_item(NAME(m_cs2));
|
save_item(NAME(m_cs2));
|
||||||
save_item(NAME(m_write));
|
save_item(NAME(m_write));
|
||||||
@ -258,13 +249,30 @@ void msm58321_device::device_timer(emu_timer &timer, device_timer_id id, int par
|
|||||||
switch (id)
|
switch (id)
|
||||||
{
|
{
|
||||||
case TIMER_CLOCK:
|
case TIMER_CLOCK:
|
||||||
|
|
||||||
|
if (m_khz_ctr & 1)
|
||||||
|
{
|
||||||
|
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)
|
if (!m_stop)
|
||||||
|
{
|
||||||
advance_seconds();
|
advance_seconds();
|
||||||
|
}
|
||||||
|
|
||||||
if (!m_busy)
|
if (!m_busy)
|
||||||
{
|
{
|
||||||
m_busy = 1;
|
m_busy = 1;
|
||||||
m_busy_handler(m_busy);
|
m_busy_handler(m_busy);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case TIMER_BUSY:
|
case TIMER_BUSY:
|
||||||
@ -274,9 +282,29 @@ void msm58321_device::device_timer(emu_timer &timer, device_timer_id id, int par
|
|||||||
m_busy_handler(m_busy);
|
m_busy_handler(m_busy);
|
||||||
}
|
}
|
||||||
break;
|
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 -
|
// 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_H1, hour);
|
||||||
write_counter(REGISTER_MI1, minute);
|
write_counter(REGISTER_MI1, minute);
|
||||||
write_counter(REGISTER_S1, second);
|
write_counter(REGISTER_S1, second);
|
||||||
|
update_standard();
|
||||||
update_output();
|
update_output();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -319,7 +347,7 @@ void msm58321_device::nvram_default()
|
|||||||
|
|
||||||
void msm58321_device::nvram_read(emu_file &file)
|
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();
|
clock_updated();
|
||||||
}
|
}
|
||||||
@ -332,7 +360,7 @@ void msm58321_device::nvram_read(emu_file &file)
|
|||||||
|
|
||||||
void msm58321_device::nvram_write(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:
|
case REGISTER_RESET:
|
||||||
data = 0;
|
data = 0;
|
||||||
break;
|
break;
|
||||||
|
case REGISTER_W:
|
||||||
case REGISTER_REF0:
|
data = m_reg[m_address] - 1;
|
||||||
case REGISTER_REF1:
|
|
||||||
// TODO: output reference values
|
|
||||||
data = 0;
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
data = m_reg[m_address];
|
data = m_reg[m_address];
|
||||||
break;
|
break;
|
||||||
@ -434,15 +458,17 @@ void msm58321_device::update_input()
|
|||||||
|
|
||||||
default:
|
default:
|
||||||
LOG("MSM58321 Register Write %s (%01x): %01x\n", reg_name(m_address), m_address, data);
|
LOG("MSM58321 Register Write %s (%01x): %01x\n", reg_name(m_address), m_address, data);
|
||||||
|
m_khz_ctr = 0;
|
||||||
switch (m_address)
|
switch (m_address)
|
||||||
{
|
{
|
||||||
case REGISTER_S10:
|
case REGISTER_S10:
|
||||||
case REGISTER_MI10:
|
case REGISTER_MI10:
|
||||||
case REGISTER_W:
|
|
||||||
m_reg[m_address] = data & 7;
|
m_reg[m_address] = data & 7;
|
||||||
break;
|
break;
|
||||||
|
case REGISTER_W:
|
||||||
|
m_reg[m_address] = (data & 7) + 1;
|
||||||
|
break;
|
||||||
case REGISTER_H10:
|
case REGISTER_H10:
|
||||||
if (data & H10_24)
|
if (data & H10_24)
|
||||||
{
|
{
|
||||||
|
@ -114,14 +114,16 @@ protected:
|
|||||||
virtual void nvram_default() override;
|
virtual void nvram_default() override;
|
||||||
virtual void nvram_read(emu_file &file) override;
|
virtual void nvram_read(emu_file &file) override;
|
||||||
virtual void nvram_write(emu_file &file) override;
|
virtual void nvram_write(emu_file &file) override;
|
||||||
|
virtual bool rtc_feature_leap_year() const override { return true; }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
static const device_timer_id TIMER_CLOCK = 0;
|
static constexpr device_timer_id TIMER_CLOCK = 0;
|
||||||
static const device_timer_id TIMER_BUSY = 1;
|
static constexpr device_timer_id TIMER_BUSY = 1;
|
||||||
|
static constexpr device_timer_id TIMER_STANDARD = 2;
|
||||||
|
|
||||||
void update_input();
|
void update_input();
|
||||||
void update_output();
|
void update_output();
|
||||||
|
void update_standard();
|
||||||
inline int read_counter(int counter);
|
inline int read_counter(int counter);
|
||||||
inline void write_counter(int counter, int value);
|
inline void write_counter(int counter, int value);
|
||||||
|
|
||||||
@ -151,11 +153,14 @@ private:
|
|||||||
int m_cs1; // chip select 1
|
int m_cs1; // chip select 1
|
||||||
|
|
||||||
uint8_t m_address; // address latch
|
uint8_t m_address; // address latch
|
||||||
uint8_t m_reg[13]; // registers
|
std::array<uint8_t, 16> m_reg; // registers
|
||||||
|
|
||||||
// timers
|
// timers
|
||||||
emu_timer *m_clock_timer;
|
emu_timer *m_clock_timer;
|
||||||
emu_timer *m_busy_timer;
|
emu_timer *m_busy_timer;
|
||||||
|
emu_timer *m_standard_timer;
|
||||||
|
|
||||||
|
int m_khz_ctr;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
@ -195,11 +195,14 @@ void device_rtc_interface::advance_days()
|
|||||||
m_register[RTC_DAY_OF_WEEK] = 1;
|
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])
|
||||||
{
|
{
|
||||||
|
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_DAY] = 1;
|
||||||
m_register[RTC_MONTH]++;
|
m_register[RTC_MONTH]++;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (m_register[RTC_MONTH] == 13)
|
if (m_register[RTC_MONTH] == 13)
|
||||||
{
|
{
|
||||||
|
Loading…
Reference in New Issue
Block a user