mirror of
https://github.com/holub/mame
synced 2025-05-05 13:54:42 +03:00
MM58167: implemented IRQs and counters write, this allow to pass the K803 diagnostic test. (nw)
dirtc: call clock_updated() after increasing the minutes counter. (nw)
This commit is contained in:
parent
98c4b826c3
commit
55d38c3753
@ -129,5 +129,5 @@ WRITE_LINE_MEMBER(dmv_k803_device::rtc_irq_w)
|
|||||||
void dmv_k803_device::update_int()
|
void dmv_k803_device::update_int()
|
||||||
{
|
{
|
||||||
bool state = ((m_latch & 0x80) && m_rtc_int);
|
bool state = ((m_latch & 0x80) && m_rtc_int);
|
||||||
m_bus->m_out_irq_cb(state ? ASSERT_LINE : CLEAR_LINE);
|
m_bus->m_out_int_cb(state ? ASSERT_LINE : CLEAR_LINE);
|
||||||
}
|
}
|
||||||
|
@ -177,6 +177,10 @@ void device_rtc_interface::advance_minutes()
|
|||||||
m_register[RTC_HOUR] = 0;
|
m_register[RTC_HOUR] = 0;
|
||||||
advance_days();
|
advance_days();
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
clock_updated();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -2,7 +2,7 @@
|
|||||||
|
|
||||||
mm58167.c - National Semiconductor MM58167 real-time clock emulation
|
mm58167.c - National Semiconductor MM58167 real-time clock emulation
|
||||||
|
|
||||||
TODO: alarms and IRQs not used by the Apple /// and aren't implemented.
|
TODO: standby interrupt
|
||||||
|
|
||||||
**********************************************************************/
|
**********************************************************************/
|
||||||
|
|
||||||
@ -70,6 +70,8 @@ void mm58167_device::device_start()
|
|||||||
|
|
||||||
// state saving
|
// state saving
|
||||||
save_item(NAME(m_regs));
|
save_item(NAME(m_regs));
|
||||||
|
save_item(NAME(m_milliseconds));
|
||||||
|
save_item(NAME(m_comparator_state));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -82,7 +84,9 @@ void mm58167_device::device_reset()
|
|||||||
set_current_time(machine());
|
set_current_time(machine());
|
||||||
|
|
||||||
m_regs[R_CTL_STATUS] = 0; // not busy
|
m_regs[R_CTL_STATUS] = 0; // not busy
|
||||||
|
m_regs[R_CTL_IRQSTATUS] = 0;
|
||||||
m_milliseconds = 0;
|
m_milliseconds = 0;
|
||||||
|
m_comparator_state = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -101,12 +105,49 @@ void mm58167_device::device_timer(emu_timer &timer, device_timer_id id, int para
|
|||||||
|
|
||||||
if (m_milliseconds >= 999)
|
if (m_milliseconds >= 999)
|
||||||
{
|
{
|
||||||
|
int old_seconds = m_regs[R_CNT_SECONDS];
|
||||||
|
int old_minutes = m_regs[R_CNT_MINUTES];
|
||||||
|
int old_hours = m_regs[R_CNT_HOURS];
|
||||||
|
int old_dayofmonth = m_regs[R_CNT_DAYOFMONTH];
|
||||||
|
int old_dayofweek = m_regs[R_CNT_DAYOFWEEK];
|
||||||
|
int old_month = m_regs[R_CNT_MONTH];
|
||||||
|
|
||||||
advance_seconds();
|
advance_seconds();
|
||||||
m_milliseconds = 0;
|
m_milliseconds = 0;
|
||||||
|
|
||||||
|
if ((m_regs[R_CTL_IRQCONTROL] & 0x04) && m_regs[R_CNT_SECONDS] != old_seconds) set_irq(2); // every second
|
||||||
|
if ((m_regs[R_CTL_IRQCONTROL] & 0x08) && m_regs[R_CNT_MINUTES] != old_minutes) set_irq(3); // every minute
|
||||||
|
if ((m_regs[R_CTL_IRQCONTROL] & 0x10) && m_regs[R_CNT_HOURS] != old_hours) set_irq(4); // every hour
|
||||||
|
if ((m_regs[R_CTL_IRQCONTROL] & 0x20) && m_regs[R_CNT_DAYOFMONTH] != old_dayofmonth) set_irq(5); // every day
|
||||||
|
if ((m_regs[R_CTL_IRQCONTROL] & 0x40) && m_regs[R_CNT_DAYOFWEEK] < old_dayofweek) set_irq(6); // every week
|
||||||
|
if ((m_regs[R_CTL_IRQCONTROL] & 0x80) && m_regs[R_CNT_MONTH] != old_month) set_irq(7); // every month
|
||||||
}
|
}
|
||||||
|
|
||||||
m_regs[R_CNT_MILLISECONDS] = make_bcd(m_milliseconds % 10);
|
m_regs[R_CNT_MILLISECONDS] = make_bcd(m_milliseconds % 10);
|
||||||
m_regs[R_CNT_HUNDTENTHS] = make_bcd(m_milliseconds / 10);
|
m_regs[R_CNT_HUNDTENTHS] = make_bcd(m_milliseconds / 10);
|
||||||
|
|
||||||
|
// 10Hz IRQ
|
||||||
|
if ((m_regs[R_CTL_IRQCONTROL] & 0x02) && (m_milliseconds % 100) == 0)
|
||||||
|
set_irq(1);
|
||||||
|
|
||||||
|
// comparator IRQ
|
||||||
|
bool new_state = true;
|
||||||
|
for (int i = R_CNT_MILLISECONDS; i <= R_CNT_MONTH; i++)
|
||||||
|
{
|
||||||
|
// nibbles that have the 2 MSB set always compares true
|
||||||
|
// Milliseconds use only the high nibble and Day of Week only the low nibble
|
||||||
|
if ((i != R_CNT_MILLISECONDS && (m_regs[i + 8] & 0x0c) != 0x0c && (m_regs[i + 8] & 0x0f) != (m_regs[i] & 0x0f)) ||
|
||||||
|
(i != R_CNT_DAYOFWEEK && (m_regs[i + 8] & 0xc0) != 0xc0 && (m_regs[i + 8] & 0xf0) != (m_regs[i] & 0xf0)))
|
||||||
|
{
|
||||||
|
new_state = false;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((m_regs[R_CTL_IRQCONTROL] & 0x01) && !m_comparator_state && new_state) // positive-edge-triggered
|
||||||
|
set_irq(0);
|
||||||
|
|
||||||
|
m_comparator_state = new_state;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -124,9 +165,36 @@ void mm58167_device::rtc_clock_updated(int year, int month, int day, int day_of_
|
|||||||
m_regs[R_CNT_MONTH] = make_bcd(month); // month (BCD)
|
m_regs[R_CNT_MONTH] = make_bcd(month); // month (BCD)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void mm58167_device::set_irq(int bit)
|
||||||
|
{
|
||||||
|
m_regs[R_CTL_IRQSTATUS] |= (1 << bit);
|
||||||
|
m_irq_w(ASSERT_LINE);
|
||||||
|
}
|
||||||
|
|
||||||
|
void mm58167_device::update_rtc()
|
||||||
|
{
|
||||||
|
set_clock_register(RTC_SECOND, bcd_to_integer(m_regs[R_CNT_SECONDS]));
|
||||||
|
set_clock_register(RTC_MINUTE, bcd_to_integer(m_regs[R_CNT_MINUTES]));
|
||||||
|
set_clock_register(RTC_HOUR, bcd_to_integer(m_regs[R_CNT_HOURS]));
|
||||||
|
set_clock_register(RTC_DAY, bcd_to_integer(m_regs[R_CNT_DAYOFMONTH]));
|
||||||
|
set_clock_register(RTC_DAY_OF_WEEK, bcd_to_integer(m_regs[R_CNT_DAYOFWEEK]));
|
||||||
|
set_clock_register(RTC_MONTH, bcd_to_integer(m_regs[R_CNT_MONTH]));
|
||||||
|
m_milliseconds = (bcd_to_integer(m_regs[R_CNT_HUNDTENTHS]) * 10) + (bcd_to_integer(m_regs[R_CNT_MILLISECONDS] >> 4) % 10);
|
||||||
|
}
|
||||||
|
|
||||||
READ8_MEMBER(mm58167_device::read)
|
READ8_MEMBER(mm58167_device::read)
|
||||||
{
|
{
|
||||||
// printf("read reg %x = %02x\n", offset, m_regs[offset]);
|
// printf("read reg %x = %02x\n", offset, m_regs[offset]);
|
||||||
|
|
||||||
|
if (offset == R_CTL_IRQSTATUS && !space.debugger_access())
|
||||||
|
{
|
||||||
|
// reading the IRQ status clears IRQ line and IRQ status
|
||||||
|
UINT8 data = m_regs[offset];
|
||||||
|
m_regs[R_CTL_IRQSTATUS] = 0;
|
||||||
|
m_irq_w(CLEAR_LINE);
|
||||||
|
return data;
|
||||||
|
}
|
||||||
|
|
||||||
return m_regs[offset];
|
return m_regs[offset];
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -141,11 +209,35 @@ WRITE8_MEMBER(mm58167_device::write)
|
|||||||
|
|
||||||
switch (offset)
|
switch (offset)
|
||||||
{
|
{
|
||||||
|
case R_CNT_MILLISECONDS:
|
||||||
|
case R_CNT_HUNDTENTHS:
|
||||||
|
case R_CNT_SECONDS:
|
||||||
|
case R_CNT_MINUTES:
|
||||||
|
case R_CNT_HOURS:
|
||||||
|
case R_CNT_DAYOFWEEK:
|
||||||
|
case R_CNT_DAYOFMONTH:
|
||||||
|
case R_CNT_MONTH:
|
||||||
|
m_regs[offset] = data;
|
||||||
|
update_rtc();
|
||||||
|
break;
|
||||||
|
|
||||||
// any write to this starts at the current time and zero milliseconds
|
// any write to this starts at the current time and zero milliseconds
|
||||||
case R_CTL_GOCMD:
|
case R_CTL_GOCMD:
|
||||||
m_milliseconds = 0;
|
m_milliseconds = 0;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case R_CTL_RESETCOUNTERS:
|
||||||
|
if (data == 0xff)
|
||||||
|
{
|
||||||
|
for (int i = R_CNT_MILLISECONDS; i <= R_CNT_MONTH; i++)
|
||||||
|
{
|
||||||
|
m_regs[i] = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
update_rtc();
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
case R_CTL_RESETRAM:
|
case R_CTL_RESETRAM:
|
||||||
if (data == 0xff)
|
if (data == 0xff)
|
||||||
{
|
{
|
||||||
|
@ -53,9 +53,13 @@ protected:
|
|||||||
virtual void rtc_clock_updated(int year, int month, int day, int day_of_week, int hour, int minute, int second);
|
virtual void rtc_clock_updated(int year, int month, int day, int day_of_week, int hour, int minute, int second);
|
||||||
virtual bool rtc_feature_leap_year() { return true; }
|
virtual bool rtc_feature_leap_year() { return true; }
|
||||||
|
|
||||||
|
void set_irq(int bit);
|
||||||
|
void update_rtc();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
int m_regs[32];
|
int m_regs[32];
|
||||||
int m_milliseconds;
|
int m_milliseconds;
|
||||||
|
bool m_comparator_state;
|
||||||
|
|
||||||
// timers
|
// timers
|
||||||
emu_timer *m_clock_timer;
|
emu_timer *m_clock_timer;
|
||||||
|
Loading…
Reference in New Issue
Block a user