modernized the MM58274C RTC device. [Fabio Priuli]

This commit is contained in:
Fabio Priuli 2013-06-01 13:27:40 +00:00
parent 17cc34dc37
commit ef44a8dc38
11 changed files with 406 additions and 447 deletions

View File

@ -19,37 +19,7 @@
***************************************************************************/ ***************************************************************************/
#include "emu.h" #include "emu.h"
#include "mm58274c.h" #include "machine/mm58274c.h"
struct mm58274c_t
{
const mm58274c_interface *intf;
int status; /* status register (*read* from address 0 = control register) */
int control; /* control register (*write* to address 0) */
int clk_set; /* clock setting register */
int int_ctl; /* interrupt control register */
int wday; /* day of the week (1-7 (1=day1 as set in init)) */
int years1; /* years (BCD: 0-99) */
int years2;
int months1; /* months (BCD: 1-12) */
int months2;
int days1; /* days (BCD: 1-31) */
int days2;
int hours1; /* hours (BCD : 0-23) */
int hours2;
int minutes1; /* minutes (BCD : 0-59) */
int minutes2;
int seconds1; /* seconds (BCD : 0-59) */
int seconds2;
int tenths; /* tenths of second (BCD : 0-9) */
emu_timer *increment_rtc;
emu_timer *interrupt_timer;
};
enum enum
{ {
@ -71,15 +41,113 @@ enum
}; };
INLINE mm58274c_t *get_safe_token(device_t *device)
{
assert(device != NULL);
assert(device->type() == MM58274C);
return (mm58274c_t *)downcast<mm58274c_device *>(device)->token(); const device_type MM58274C = &device_creator<mm58274c_device>;
mm58274c_device::mm58274c_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock)
: device_t(mconfig, MM58274C, "National Semiconductor MM58274C", tag, owner, clock)
{
} }
static attotime interrupt_period_table(int val)
//-------------------------------------------------
// device_config_complete - perform any
// operations now that the configuration is
// complete
//-------------------------------------------------
void mm58274c_device::device_config_complete()
{
// inherit a copy of the static data
const mm58274c_interface *intf = reinterpret_cast<const mm58274c_interface *>(static_config());
if (intf != NULL)
*static_cast<mm58274c_interface *>(this) = *intf;
// or initialize to defaults if none provided
else
{
m_mode24 = 0;
m_day1 = 0;
}
}
//-------------------------------------------------
// device_start - device-specific startup
//-------------------------------------------------
void mm58274c_device::device_start()
{
m_increment_rtc = machine().scheduler().timer_alloc(timer_expired_delegate(FUNC(mm58274c_device::rtc_increment_cb),this));
m_increment_rtc->adjust(attotime::zero, 0, attotime::from_msec(100));
m_interrupt_timer = machine().scheduler().timer_alloc(timer_expired_delegate(FUNC(mm58274c_device::rtc_interrupt_cb),this));
// register for state saving
save_item(NAME(m_status));
save_item(NAME(m_control));
save_item(NAME(m_clk_set));
save_item(NAME(m_int_ctl));
save_item(NAME(m_wday));
save_item(NAME(m_years1));
save_item(NAME(m_years2));
save_item(NAME(m_months1));
save_item(NAME(m_months2));
save_item(NAME(m_days1));
save_item(NAME(m_days2));
save_item(NAME(m_hours1));
save_item(NAME(m_hours2));
save_item(NAME(m_minutes1));
save_item(NAME(m_minutes2));
save_item(NAME(m_seconds1));
save_item(NAME(m_seconds2));
save_item(NAME(m_tenths));
}
//-------------------------------------------------
// device_reset - device-specific reset
//-------------------------------------------------
void mm58274c_device::device_reset()
{
system_time systime;
/* get the current date/time from the core */
machine().current_datetime(systime);
m_clk_set = systime.local_time.year & 3 << 2;
if (m_mode24)
m_clk_set |= clk_set_24;
/* The clock count starts on 1st January 1900 */
m_wday = 1 + ((systime.local_time.weekday - m_day1) % 7);
m_years1 = (systime.local_time.year / 10) % 10;
m_years2 = systime.local_time.year % 10;
m_months1 = (systime.local_time.month + 1) / 10;
m_months2 = (systime.local_time.month + 1) % 10;
m_days1 = systime.local_time.mday / 10;
m_days2 = systime.local_time.mday % 10;
if (!m_mode24)
{
/* 12-hour mode */
if (systime.local_time.hour > 12)
{
systime.local_time.hour -= 12;
m_clk_set |= clk_set_pm;
}
if (systime.local_time.hour == 0)
systime.local_time.hour = 12;
}
m_hours1 = systime.local_time.hour / 10;
m_hours2 = systime.local_time.hour % 10;
m_minutes1 = systime.local_time.minute / 10;
m_minutes2 = systime.local_time.minute % 10;
m_seconds1 = systime.local_time.second / 10;
m_seconds2 = systime.local_time.second % 10;
m_tenths = 0;
}
attotime mm58274c_device::interrupt_period_table(int val)
{ {
switch(val) switch(val)
{ {
@ -95,295 +163,273 @@ static attotime interrupt_period_table(int val)
} }
}; };
READ8_DEVICE_HANDLER( mm58274c_r ) READ8_MEMBER( mm58274c_device::read )
{ {
mm58274c_t *mm58274c = get_safe_token(device);
int reply; int reply;
offset &= 0xf; offset &= 0xf;
switch (offset) switch (offset)
{ {
case 0x0: /* Control Register */ case 0x00: /* Control Register */
reply = mm58274c->status; reply = m_status;
mm58274c->status = 0; m_status = 0;
break; break;
case 0x1: /* Tenths of Seconds */ case 0x01: /* Tenths of Seconds */
reply = mm58274c->tenths; reply = m_tenths;
break; break;
case 0x2: /* Units Seconds */ case 0x02: /* Units Seconds */
reply = mm58274c->seconds2; reply = m_seconds2;
break; break;
case 0x3: /* Tens Seconds */ case 0x03: /* Tens Seconds */
reply = mm58274c->seconds1; reply = m_seconds1;
break; break;
case 0x04: /* Units Minutes */ case 0x04: /* Units Minutes */
reply = mm58274c->minutes2; reply = m_minutes2;
break; break;
case 0x5: /* Tens Minutes */ case 0x05: /* Tens Minutes */
reply = mm58274c->minutes1; reply = m_minutes1;
break; break;
case 0x6: /* Units Hours */ case 0x06: /* Units Hours */
reply = mm58274c->hours2; reply = m_hours2;
break; break;
case 0x7: /* Tens Hours */ case 0x07: /* Tens Hours */
reply = mm58274c->hours1; reply = m_hours1;
break; break;
case 0x8: /* Units Days */ case 0x08: /* Units Days */
reply = mm58274c->days2; reply = m_days2;
break; break;
case 0x9: /* Tens Days */ case 0x09: /* Tens Days */
reply = mm58274c->days1; reply = m_days1;
break; break;
case 0xA: /* Units Months */ case 0x0a: /* Units Months */
reply = mm58274c->months2; reply = m_months2;
break; break;
case 0xB: /* Tens Months */ case 0x0b: /* Tens Months */
reply = mm58274c->months1; reply = m_months1;
break; break;
case 0xC: /* Units Years */ case 0x0c: /* Units Years */
reply = mm58274c->years2; reply = m_years2;
break; break;
case 0xD: /* Tens Years */ case 0x0d: /* Tens Years */
reply = mm58274c->years1; reply = m_years1;
break; break;
case 0xE: /* Day of Week */ case 0x0e: /* Day of Week */
reply = mm58274c->wday; reply = m_wday;
break; break;
case 0xF: /* Clock Setting & Interrupt Registers */ case 0x0f: /* Clock Setting & Interrupt Registers */
if (mm58274c->control & ctl_intsel) if (m_control & ctl_intsel) /* interrupt register */
/* interrupt register */ reply = m_int_ctl;
reply = mm58274c->int_ctl; else /* clock setting register */
else {
{ /* clock setting register */ if (m_clk_set & clk_set_24) /* 24-hour mode */
if (mm58274c->clk_set & clk_set_24) reply = m_clk_set & ~clk_set_pm;
/* 24-hour mode */ else /* 12-hour mode */
reply = mm58274c->clk_set & ~clk_set_pm; reply = m_clk_set;
else }
/* 12-hour mode */ break;
reply = mm58274c->clk_set;
}
break;
default: default:
reply = 0; reply = 0;
break; break;
} }
return reply; return reply;
} }
WRITE8_DEVICE_HANDLER (mm58274c_w) WRITE8_MEMBER( mm58274c_device::write )
{ {
mm58274c_t *mm58274c = get_safe_token(device);
offset &= 0xf; offset &= 0xf;
data &= 0xf; data &= 0xf;
switch (offset) switch (offset)
{ {
case 0x0: /* Control Register (test mode and interrupt not emulated) */ case 0x00: /* Control Register (test mode and interrupt not emulated) */
if ((! (mm58274c->control & ctl_intstop)) && (data & ctl_intstop)) if ((!(m_control & ctl_intstop)) && (data & ctl_intstop)) /* interrupt stop */
/* interrupt stop */ m_interrupt_timer->enable(0);
mm58274c->interrupt_timer->enable(0); else if ((m_control & ctl_intstop) && (!(data & ctl_intstop))) /* interrupt run */
else if ((mm58274c->control & ctl_intstop) && (! (data & ctl_intstop)))
{
/* interrupt run */
attotime period = interrupt_period_table(mm58274c->int_ctl & int_ctl_dly);
mm58274c->interrupt_timer->adjust(period, 0, mm58274c->int_ctl & int_ctl_rpt ? period : attotime::zero);
}
if (data & ctl_clkstop)
/* stopping the clock clears the tenth counter */
mm58274c->tenths = 0;
mm58274c->control = data;
break;
case 0x1: /* Tenths of Seconds: cannot be written */
break;
case 0x2: /* Units Seconds */
mm58274c->seconds2 = data;
break;
case 0x3: /* Tens Seconds */
mm58274c->seconds1 = data;
break;
case 0x4: /* Units Minutes */
mm58274c->minutes2 = data;
break;
case 0x5: /* Tens Minutes */
mm58274c->minutes1 = data;
break;
case 0x6: /* Units Hours */
mm58274c->hours2 = data;
break;
case 0x7: /* Tens Hours */
mm58274c->hours1 = data;
break;
case 0x8: /* Units Days */
mm58274c->days2 = data;
break;
case 0x9: /* Tens Days */
mm58274c->days1 = data;
break;
case 0xA: /* Units Months */
mm58274c->months2 = data;
break;
case 0xB: /* Tens Months */
mm58274c->months1 = data;
break;
case 0xC: /* Units Years */
mm58274c->years2 = data;
break;
case 0xD: /* Tens Years */
mm58274c->years1 = data;
break;
case 0xE: /* Day of Week */
mm58274c->wday = data;
break;
case 0xF: /* Clock Setting & Interrupt Registers */
if (mm58274c->control & ctl_intsel)
{
/* interrupt register (not emulated) */
mm58274c->int_ctl = data;
if (! (mm58274c->control & ctl_intstop))
{ {
/* interrupt run */ attotime period = interrupt_period_table(m_int_ctl & int_ctl_dly);
attotime period = interrupt_period_table(mm58274c->int_ctl & int_ctl_dly);
mm58274c->interrupt_timer->adjust(period, 0, mm58274c->int_ctl & int_ctl_rpt ? period : attotime::zero); m_interrupt_timer->adjust(period, 0, m_int_ctl & int_ctl_rpt ? period : attotime::zero);
} }
} if (data & ctl_clkstop) /* stopping the clock clears the tenth counter */
else m_tenths = 0;
{ m_control = data;
/* clock setting register */ break;
mm58274c->clk_set = data;
#if 0 case 0x01: /* Tenths of Seconds: cannot be written */
if (mm58274c->clk_set & clk_set_24) break;
/* 24-hour mode */
mm58274c->clk_set &= ~clk_set_pm; case 0x02: /* Units Seconds */
#endif m_seconds2 = data;
} break;
break;
case 0x03: /* Tens Seconds */
m_seconds1 = data;
break;
case 0x04: /* Units Minutes */
m_minutes2 = data;
break;
case 0x05: /* Tens Minutes */
m_minutes1 = data;
break;
case 0x06: /* Units Hours */
m_hours2 = data;
break;
case 0x07: /* Tens Hours */
m_hours1 = data;
break;
case 0x08: /* Units Days */
m_days2 = data;
break;
case 0x09: /* Tens Days */
m_days1 = data;
break;
case 0x0a: /* Units Months */
m_months2 = data;
break;
case 0x0b: /* Tens Months */
m_months1 = data;
break;
case 0x0c: /* Units Years */
m_years2 = data;
break;
case 0x0d: /* Tens Years */
m_years1 = data;
break;
case 0x0e: /* Day of Week */
m_wday = data;
break;
case 0x0f: /* Clock Setting & Interrupt Registers */
if (m_control & ctl_intsel) /* interrupt register (not emulated) */
{
m_int_ctl = data;
if (!(m_control & ctl_intstop)) /* interrupt run */
{
attotime period = interrupt_period_table(m_int_ctl & int_ctl_dly);
m_interrupt_timer->adjust(period, 0, m_int_ctl & int_ctl_rpt ? period : attotime::zero);
}
}
else /* clock setting register */
{
m_clk_set = data;
#if 0
if (m_clk_set & clk_set_24) /* 24-hour mode */
m_clk_set &= ~clk_set_pm;
#endif
}
break;
} }
} }
/* // Set RTC interrupt flag
Set RTC interrupt flag TIMER_CALLBACK_MEMBER(mm58274c_device::rtc_interrupt_cb)
*/
static TIMER_CALLBACK(rtc_interrupt_callback)
{ {
device_t *device = (device_t *)ptr; m_status |= st_if;
mm58274c_t *mm58274c = get_safe_token(device);
mm58274c->status |= st_if;
} }
/* // Increment RTC clock (timed interrupt every 1/10s)
Increment RTC clock (timed interrupt every 1/10s) TIMER_CALLBACK_MEMBER(mm58274c_device::rtc_increment_cb)
*/
static TIMER_CALLBACK(increment_rtc)
{ {
device_t *device = (device_t *)ptr; if (!(m_control & ctl_clkstop))
mm58274c_t *mm58274c = get_safe_token(device);
if (! (mm58274c->control & ctl_clkstop))
{ {
mm58274c->status |= st_dcf; m_status |= st_dcf;
if ((++mm58274c->tenths) == 10) if ((++m_tenths) == 10)
{ {
mm58274c->tenths = 0; m_tenths = 0;
if ((++mm58274c->seconds2) == 10) if ((++m_seconds2) == 10)
{ {
mm58274c->seconds2 = 0; m_seconds2 = 0;
if ((++mm58274c->seconds1) == 6) if ((++m_seconds1) == 6)
{ {
mm58274c->seconds1 = 0; m_seconds1 = 0;
if ((++mm58274c->minutes2) == 10) if ((++m_minutes2) == 10)
{ {
mm58274c->minutes2 = 0; m_minutes2 = 0;
if ((++mm58274c->minutes1) == 6) if ((++m_minutes1) == 6)
{ {
mm58274c->minutes1 = 0; m_minutes1 = 0;
if ((++mm58274c->hours2) == 10) if ((++m_hours2) == 10)
{ {
mm58274c->hours2 = 0; m_hours2 = 0;
mm58274c->hours1++; m_hours1++;
} }
/* handle wrap-around */ /* handle wrap-around */
if ((! (mm58274c->clk_set & clk_set_24)) if ((!(m_clk_set & clk_set_24))
&& ((mm58274c->hours1*10 + mm58274c->hours2) == 12)) && ((m_hours1*10 + m_hours2) == 12))
{ {
mm58274c->clk_set ^= clk_set_pm; m_clk_set ^= clk_set_pm;
} }
if ((! (mm58274c->clk_set & clk_set_24)) if ((!(m_clk_set & clk_set_24))
&& ((mm58274c->hours1*10 + mm58274c->hours2) == 13)) && ((m_hours1*10 + m_hours2) == 13))
{ {
mm58274c->hours1 = 0; m_hours1 = 0;
mm58274c->hours2 = 1; m_hours2 = 1;
} }
if ((mm58274c->clk_set & clk_set_24) if ((m_clk_set & clk_set_24)
&& ((mm58274c->hours1*10 + mm58274c->hours2) == 24)) && ((m_hours1*10 + m_hours2) == 24))
{ {
mm58274c->hours1 = mm58274c->hours2 = 0; m_hours1 = m_hours2 = 0;
} }
/* increment day if needed */ /* increment day if needed */
if ((mm58274c->clk_set & clk_set_24) if ((m_clk_set & clk_set_24)
? ((mm58274c->hours1*10 + mm58274c->hours2) == 0) ? ((m_hours1*10 + m_hours2) == 0)
: (((mm58274c->hours1*10 + mm58274c->hours2) == 12) : (((m_hours1*10 + m_hours2) == 12)
&& (! (mm58274c->clk_set & clk_set_pm)))) && (!(m_clk_set & clk_set_pm))))
{ {
int days_in_month; int days_in_month;
if ((++mm58274c->days2) == 10) if ((++m_days2) == 10)
{ {
mm58274c->days2 = 0; m_days2 = 0;
mm58274c->days1++; m_days1++;
} }
if ((++mm58274c->wday) == 8) if ((++m_wday) == 8)
mm58274c->wday = 1; m_wday = 1;
{ {
static const int days_in_month_array[] = static const int days_in_month_array[] =
@ -392,39 +438,39 @@ static TIMER_CALLBACK(increment_rtc)
31,31,30, 31,30,31 31,31,30, 31,30,31
}; };
if (((mm58274c->months1*10 + mm58274c->months2) != 2) || (mm58274c->clk_set & clk_set_leap)) if (((m_months1*10 + m_months2) != 2) || (m_clk_set & clk_set_leap))
days_in_month = days_in_month_array[mm58274c->months1*10 + mm58274c->months2 - 1]; days_in_month = days_in_month_array[m_months1*10 + m_months2 - 1];
else else
days_in_month = 29; days_in_month = 29;
} }
if ((mm58274c->days1*10 + mm58274c->days2) == days_in_month+1) if ((m_days1*10 + m_days2) == days_in_month+1)
{ {
mm58274c->days1 = 0; m_days1 = 0;
mm58274c->days2 = 1; m_days2 = 1;
if ((++mm58274c->months2) == 10) if ((++m_months2) == 10)
{ {
mm58274c->months2 = 0; m_months2 = 0;
mm58274c->months1++; m_months1++;
} }
if ((mm58274c->months1*10 + mm58274c->months2) == 13) if ((m_months1*10 + m_months2) == 13)
{ {
mm58274c->months1 = 0; m_months1 = 0;
mm58274c->months2 = 1; m_months2 = 1;
mm58274c->clk_set = (mm58274c->clk_set & ~clk_set_leap) m_clk_set = (m_clk_set & ~clk_set_leap)
| ((mm58274c->clk_set + clk_set_leap_inc) & clk_set_leap); | ((m_clk_set + clk_set_leap_inc) & clk_set_leap);
if ((++mm58274c->years2) == 10) if ((++m_years2) == 10)
{ {
mm58274c->years2 = 0; m_years2 = 0;
if ((++mm58274c->years1) == 10) if ((++m_years1) == 10)
mm58274c->years1 = 0; m_years1 = 0;
} }
} }
} }
@ -437,116 +483,3 @@ static TIMER_CALLBACK(increment_rtc)
} }
} }
/* Device Interface */
static DEVICE_START( mm58274c )
{
mm58274c_t *mm58274c = get_safe_token(device);
// validate arguments
assert(device != NULL);
assert(device->tag() != NULL);
assert(device->static_config() != NULL);
mm58274c->intf = (const mm58274c_interface*)device->static_config();
// register for state saving
state_save_register_item(device->machine(), "mm58274c", device->tag(), 0, mm58274c->status);
state_save_register_item(device->machine(), "mm58274c", device->tag(), 0, mm58274c->control);
state_save_register_item(device->machine(), "mm58274c", device->tag(), 0, mm58274c->clk_set);
state_save_register_item(device->machine(), "mm58274c", device->tag(), 0, mm58274c->int_ctl);
state_save_register_item(device->machine(), "mm58274c", device->tag(), 0, mm58274c->wday);
state_save_register_item(device->machine(), "mm58274c", device->tag(), 0, mm58274c->years1);
state_save_register_item(device->machine(), "mm58274c", device->tag(), 0, mm58274c->years2);
state_save_register_item(device->machine(), "mm58274c", device->tag(), 0, mm58274c->months1);
state_save_register_item(device->machine(), "mm58274c", device->tag(), 0, mm58274c->months2);
state_save_register_item(device->machine(), "mm58274c", device->tag(), 0, mm58274c->days1);
state_save_register_item(device->machine(), "mm58274c", device->tag(), 0, mm58274c->days2);
state_save_register_item(device->machine(), "mm58274c", device->tag(), 0, mm58274c->hours1);
state_save_register_item(device->machine(), "mm58274c", device->tag(), 0, mm58274c->hours2);
state_save_register_item(device->machine(), "mm58274c", device->tag(), 0, mm58274c->minutes1);
state_save_register_item(device->machine(), "mm58274c", device->tag(), 0, mm58274c->minutes2);
state_save_register_item(device->machine(), "mm58274c", device->tag(), 0, mm58274c->seconds1);
state_save_register_item(device->machine(), "mm58274c", device->tag(), 0, mm58274c->seconds2);
state_save_register_item(device->machine(), "mm58274c", device->tag(), 0, mm58274c->tenths);
mm58274c->increment_rtc = device->machine().scheduler().timer_alloc(FUNC(increment_rtc), ((void*)device));
mm58274c->increment_rtc->adjust(attotime::zero, 0, attotime::from_msec(100));
mm58274c->interrupt_timer = device->machine().scheduler().timer_alloc(FUNC(rtc_interrupt_callback), ((void*)device));
}
static DEVICE_RESET( mm58274c )
{
mm58274c_t *mm58274c = get_safe_token(device);
system_time systime;
/* get the current date/time from the core */
device->machine().current_datetime(systime);
mm58274c->clk_set = systime.local_time.year & 3 << 2;
if (mm58274c->intf->mode24)
mm58274c->clk_set |= clk_set_24;
/* The clock count starts on 1st January 1900 */
mm58274c->wday = 1 + ((systime.local_time.weekday - mm58274c->intf->day1)%7);
mm58274c->years1 = (systime.local_time.year / 10) % 10;
mm58274c->years2 = systime.local_time.year % 10;
mm58274c->months1 = (systime.local_time.month + 1) / 10;
mm58274c->months2 = (systime.local_time.month + 1) % 10;
mm58274c->days1 = systime.local_time.mday / 10;
mm58274c->days2 = systime.local_time.mday % 10;
if (!mm58274c->intf->mode24)
{
/* 12-hour mode */
if (systime.local_time.hour > 12)
{
systime.local_time.hour -= 12;
mm58274c->clk_set |= clk_set_pm;
}
if (systime.local_time.hour == 0)
systime.local_time.hour = 12;
}
mm58274c->hours1 = systime.local_time.hour / 10;
mm58274c->hours2 = systime.local_time.hour % 10;
mm58274c->minutes1 = systime.local_time.minute / 10;
mm58274c->minutes2 = systime.local_time.minute % 10;
mm58274c->seconds1 = systime.local_time.second / 10;
mm58274c->seconds2 = systime.local_time.second % 10;
mm58274c->tenths = 0;
}
const device_type MM58274C = &device_creator<mm58274c_device>;
mm58274c_device::mm58274c_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock)
: device_t(mconfig, MM58274C, "National Semiconductor MM58274C", tag, owner, clock)
{
m_token = global_alloc_clear(mm58274c_t);
}
//-------------------------------------------------
// device_config_complete - perform any
// operations now that the configuration is
// complete
//-------------------------------------------------
void mm58274c_device::device_config_complete()
{
}
//-------------------------------------------------
// device_start - device-specific startup
//-------------------------------------------------
void mm58274c_device::device_start()
{
DEVICE_START_NAME( mm58274c )(this);
}
//-------------------------------------------------
// device_reset - device-specific reset
//-------------------------------------------------
void mm58274c_device::device_reset()
{
DEVICE_RESET_NAME( mm58274c )(this);
}

View File

@ -1,50 +1,77 @@
#ifndef MM58274C_H #ifndef __MM58274C_H__
#define MM58274C_H #define __MM58274C_H__
/*
Initializes the clock chip.
day1 must be set to a value from 0 (sunday), 1 (monday) ...
to 6 (saturday) and is needed to correctly retrieve the day-of-week
from the host system clock.
*/
struct mm58274c_interface
{
int m_mode24; /* 24/12 mode */
int m_day1; /* first day of week */
};
/*************************************************************************** /***************************************************************************
MACROS MACROS
***************************************************************************/ ***************************************************************************/
class mm58274c_device : public device_t class mm58274c_device : public device_t,
public mm58274c_interface
{ {
public: public:
mm58274c_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock); mm58274c_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock);
~mm58274c_device() { global_free(m_token); } ~mm58274c_device() {}
DECLARE_READ8_MEMBER(read);
DECLARE_WRITE8_MEMBER(write);
TIMER_CALLBACK_MEMBER(rtc_increment_cb);
TIMER_CALLBACK_MEMBER(rtc_interrupt_cb);
// access to legacy token
void *token() const { assert(m_token != NULL); return m_token; }
protected: protected:
// device-level overrides // device-level overrides
virtual void device_config_complete(); virtual void device_config_complete();
virtual void device_start(); virtual void device_start();
virtual void device_reset(); virtual void device_reset();
private: private:
// internal state // internal state
void *m_token; attotime interrupt_period_table(int val);
int m_status; /* status register (*read* from address 0 = control register) */
int m_control; /* control register (*write* to address 0) */
int m_clk_set; /* clock setting register */
int m_int_ctl; /* interrupt control register */
int m_wday; /* day of the week (1-7 (1=day1 as set in init)) */
int m_years1; /* years (BCD: 0-99) */
int m_years2;
int m_months1; /* months (BCD: 1-12) */
int m_months2;
int m_days1; /* days (BCD: 1-31) */
int m_days2;
int m_hours1; /* hours (BCD : 0-23) */
int m_hours2;
int m_minutes1; /* minutes (BCD : 0-59) */
int m_minutes2;
int m_seconds1; /* seconds (BCD : 0-59) */
int m_seconds2;
int m_tenths; /* tenths of second (BCD : 0-9) */
emu_timer *m_increment_rtc;
emu_timer *m_interrupt_timer;
}; };
extern const device_type MM58274C; extern const device_type MM58274C;
/***************************************************************************
FUNCTION PROTOTYPES
***************************************************************************/
/* interface */
/*
Initializes the clock chip.
day1 must be set to a value from 0 (sunday), 1 (monday) ...
to 6 (saturday) and is needed to correctly retrieve the day-of-week
from the host system clock.
*/
struct mm58274c_interface
{
int mode24; /* 24/12 mode */
int day1; /* first day of week */
};
DECLARE_READ8_DEVICE_HANDLER ( mm58274c_r );
DECLARE_WRITE8_DEVICE_HANDLER( mm58274c_w );
/*************************************************************************** /***************************************************************************
DEVICE CONFIGURATION MACROS DEVICE CONFIGURATION MACROS
***************************************************************************/ ***************************************************************************/
@ -53,4 +80,4 @@ DECLARE_WRITE8_DEVICE_HANDLER( mm58274c_w );
MCFG_DEVICE_ADD(_tag, MM58274C, 0) \ MCFG_DEVICE_ADD(_tag, MM58274C, 0) \
MCFG_DEVICE_CONFIG(_intrf) MCFG_DEVICE_CONFIG(_intrf)
#endif /* MM58274C_H */ #endif

View File

@ -162,7 +162,7 @@ ADDRESS_MAP_END
static ADDRESS_MAP_START( compis_io, AS_IO, 16, compis_state ) static ADDRESS_MAP_START( compis_io, AS_IO, 16, compis_state )
AM_RANGE( 0x0000, 0x0007) AM_DEVREADWRITE8("ppi8255", i8255_device, read, write, 0xff00) AM_RANGE( 0x0000, 0x0007) AM_DEVREADWRITE8("ppi8255", i8255_device, read, write, 0xff00)
AM_RANGE( 0x0080, 0x0087) AM_DEVREADWRITE8_LEGACY("pit8253", pit8253_r, pit8253_w, 0xffff) AM_RANGE( 0x0080, 0x0087) AM_DEVREADWRITE8_LEGACY("pit8253", pit8253_r, pit8253_w, 0xffff)
AM_RANGE( 0x0100, 0x011b) AM_DEVREADWRITE8_LEGACY("mm58274c", mm58274c_r, mm58274c_w, 0xffff) AM_RANGE( 0x0100, 0x011b) AM_DEVREADWRITE8("mm58274c", mm58274c_device, read, write, 0xffff)
AM_RANGE( 0x0280, 0x0283) AM_DEVREADWRITE8("pic8259_master", pic8259_device, read, write, 0xffff) /* 80150/80130 */ AM_RANGE( 0x0280, 0x0283) AM_DEVREADWRITE8("pic8259_master", pic8259_device, read, write, 0xffff) /* 80150/80130 */
//AM_RANGE( 0x0288, 0x028f) AM_DEVREADWRITE_LEGACY("pit8254", compis_osp_pit_r, compis_osp_pit_w ) /* PIT 8254 (80150/80130) */ //AM_RANGE( 0x0288, 0x028f) AM_DEVREADWRITE_LEGACY("pit8254", compis_osp_pit_r, compis_osp_pit_w ) /* PIT 8254 (80150/80130) */
AM_RANGE( 0x0310, 0x031f) AM_READWRITE( compis_usart_r, compis_usart_w ) /* USART 8251 Keyboard */ AM_RANGE( 0x0310, 0x031f) AM_READWRITE( compis_usart_r, compis_usart_w ) /* USART 8251 Keyboard */

View File

@ -35,14 +35,15 @@ public:
m_maincpu(*this, "maincpu"), m_maincpu(*this, "maincpu"),
m_acia0(*this, ACIA_0_TAG), m_acia0(*this, ACIA_0_TAG),
m_acia1(*this, ACIA_1_TAG), m_acia1(*this, ACIA_1_TAG),
m_mm58274(*this,"mm58274c"),
m_videoram(*this,"videoram") { } m_videoram(*this,"videoram") { }
required_device<cpu_device> m_maincpu; required_device<cpu_device> m_maincpu;
required_device<mos6551_device> m_acia0; required_device<mos6551_device> m_acia0;
required_device<mos6551_device> m_acia1; required_device<mos6551_device> m_acia1;
required_device<mm58274c_device> m_mm58274;
required_shared_ptr<UINT16> m_videoram; required_shared_ptr<UINT16> m_videoram;
device_t *m_mm58274;
concept_exp_port_device *m_exp[4]; concept_exp_port_device *m_exp[4];
ioport_port *m_key[6]; ioport_port *m_key[6];

View File

@ -59,8 +59,6 @@ void concept_state::machine_start()
m_KeyQueueHead = m_KeyQueueLen = 0; m_KeyQueueHead = m_KeyQueueLen = 0;
memset(m_KeyStateSave, 0, sizeof(m_KeyStateSave)); memset(m_KeyStateSave, 0, sizeof(m_KeyStateSave));
m_mm58274 = machine().device("mm58274c");
m_exp[0] = machine().device<concept_exp_port_device>("exp1"); m_exp[0] = machine().device<concept_exp_port_device>("exp1");
m_exp[1] = machine().device<concept_exp_port_device>("exp2"); m_exp[1] = machine().device<concept_exp_port_device>("exp2");
m_exp[2] = machine().device<concept_exp_port_device>("exp3"); m_exp[2] = machine().device<concept_exp_port_device>("exp3");
@ -280,7 +278,7 @@ READ16_MEMBER(concept_state::concept_io_r)
/* calendar R/W */ /* calendar R/W */
VLOG(("concept_io_r: Calendar read at address 0x03%4.4x\n", offset << 1)); VLOG(("concept_io_r: Calendar read at address 0x03%4.4x\n", offset << 1));
if (!m_clock_enable) if (!m_clock_enable)
return mm58274c_r(m_mm58274, space, m_clock_address); return m_mm58274->read(space, m_clock_address);
break; break;
case 7: case 7:
@ -405,7 +403,7 @@ WRITE16_MEMBER(concept_state::concept_io_w)
/* calendar R/W */ /* calendar R/W */
LOG(("concept_io_w: Calendar written to at address 0x03%4.4x, data: 0x%4.4x\n", offset << 1, data)); LOG(("concept_io_w: Calendar written to at address 0x03%4.4x, data: 0x%4.4x\n", offset << 1, data));
if (!m_clock_enable) if (!m_clock_enable)
mm58274c_w(m_mm58274, space, m_clock_address, data & 0xf); m_mm58274->write(space, m_clock_address, data & 0xf);
break; break;
case 7: case 7:

View File

@ -33,7 +33,6 @@
#include "machine/wd17xx.h" #include "machine/wd17xx.h"
#include "formats/ti99_dsk.h" #include "formats/ti99_dsk.h"
#include "imagedev/flopdrv.h" #include "imagedev/flopdrv.h"
#include "machine/mm58274c.h"
#define LOG logerror #define LOG logerror
#define VERBOSE 1 #define VERBOSE 1
@ -45,7 +44,8 @@
#define BUFFER "ram" #define BUFFER "ram"
snug_bwg_device::snug_bwg_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock) snug_bwg_device::snug_bwg_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock)
: ti_expansion_card_device(mconfig, TI99_BWG, "SNUG BwG Floppy Controller", tag, owner, clock, "ti99_bwg", __FILE__) : ti_expansion_card_device(mconfig, TI99_BWG, "SNUG BwG Floppy Controller", tag, owner, clock, "ti99_bwg", __FILE__),
m_clock(*this, CLOCK_TAG)
{ {
} }
@ -131,7 +131,7 @@ READ8Z_MEMBER(snug_bwg_device::readz)
if ((offset & 0x03e1)==0x03e0) if ((offset & 0x03e1)==0x03e0)
{ {
// .... ..11 111x xxx0 // .... ..11 111x xxx0
*value = mm58274c_r(m_clock, space, (offset & 0x001e) >> 1); *value = m_clock->read(space, (offset & 0x001e) >> 1);
} }
else else
{ {
@ -210,7 +210,7 @@ WRITE8_MEMBER(snug_bwg_device::write)
if ((offset & 0x03e1)==0x03e0) if ((offset & 0x03e1)==0x03e0)
{ {
// .... ..11 111x xxx0 // .... ..11 111x xxx0
mm58274c_w(m_clock, space, (offset & 0x001e) >> 1, data); m_clock->write(space, (offset & 0x001e) >> 1, data);
} }
else else
{ {
@ -386,7 +386,6 @@ void snug_bwg_device::device_start(void)
m_buffer_ram = memregion(BUFFER)->base(); m_buffer_ram = memregion(BUFFER)->base();
m_motor_on_timer = timer_alloc(MOTOR_TIMER); m_motor_on_timer = timer_alloc(MOTOR_TIMER);
m_controller = subdevice(FDC_TAG); m_controller = subdevice(FDC_TAG);
m_clock = subdevice(CLOCK_TAG);
m_cru_base = 0x1100; m_cru_base = 0x1100;
} }

View File

@ -14,6 +14,7 @@
#include "ti99defs.h" #include "ti99defs.h"
#include "imagedev/flopdrv.h" #include "imagedev/flopdrv.h"
#include "machine/mm58274c.h"
extern const device_type TI99_BWG; extern const device_type TI99_BWG;
@ -79,7 +80,7 @@ private:
device_t* m_controller; device_t* m_controller;
// Link to the real-time clock on the board. // Link to the real-time clock on the board.
device_t* m_clock; required_device<mm58274c_device> m_clock;
// count 4.23s from rising edge of motor_on // count 4.23s from rising edge of motor_on
emu_timer* m_motor_on_timer; emu_timer* m_motor_on_timer;

View File

@ -141,7 +141,6 @@
***************************************************************************/ ***************************************************************************/
#include "genboard.h" #include "genboard.h"
#include "machine/mm58274c.h"
#define VERBOSE 1 #define VERBOSE 1
#define LOG logerror #define LOG logerror
@ -338,7 +337,7 @@ READ8_MEMBER( geneve_mapper_device::readm )
// clock // clock
// tests on the real machine showed that // tests on the real machine showed that
// upper nibble is 0xf (probably because of the location at 0xf130?) // upper nibble is 0xf (probably because of the location at 0xf130?)
value = mm58274c_r(m_clock, space, offset & 0x000f) | 0xf0; value = m_clock->read(space, offset & 0x000f) | 0xf0;
do_wait(1); do_wait(1);
if (VERBOSE>7) LOG("genboard: Read clock %04x -> %02x\n", offset, value); if (VERBOSE>7) LOG("genboard: Read clock %04x -> %02x\n", offset, value);
return value; return value;
@ -372,7 +371,7 @@ READ8_MEMBER( geneve_mapper_device::readm )
// Obscure, needs more investigation. We might as well ignore this, // Obscure, needs more investigation. We might as well ignore this,
// as the high nibble is obviously undefined and takes some past // as the high nibble is obviously undefined and takes some past
// value floating around. // value floating around.
value = mm58274c_r(m_clock, space, offset & 0x000f); value = m_clock->read(space, offset & 0x000f);
value |= ((offset & 0x000f)==0x000f)? 0x20 : 0x10; value |= ((offset & 0x000f)==0x000f)? 0x20 : 0x10;
do_wait(1); do_wait(1);
@ -609,7 +608,7 @@ WRITE8_MEMBER( geneve_mapper_device::writem )
{ {
// clock // clock
// ++++ ++++ ++++ ---- // ++++ ++++ ++++ ----
mm58274c_w(m_clock, space, offset & 0x00f, data); m_clock->write(space, offset & 0x00f, data);
do_wait(1); do_wait(1);
if (VERBOSE>7) LOG("genboard: Write clock %04x <- %02x\n", offset, data); if (VERBOSE>7) LOG("genboard: Write clock %04x <- %02x\n", offset, data);
return; return;
@ -630,7 +629,7 @@ WRITE8_MEMBER( geneve_mapper_device::writem )
if ((offset & 0xfff0)==0x8010) if ((offset & 0xfff0)==0x8010)
{ {
// clock // clock
mm58274c_w(m_clock, space, offset & 0x00f, data); m_clock->write(space, offset & 0x00f, data);
do_wait(1); do_wait(1);
if (VERBOSE>7) LOG("genboard: Write clock %04x <- %02x\n", offset, data); if (VERBOSE>7) LOG("genboard: Write clock %04x <- %02x\n", offset, data);
return; return;
@ -834,7 +833,7 @@ void geneve_mapper_device::device_start()
m_keyboard = machine().device<geneve_keyboard_device>(GKEYBOARD_TAG); m_keyboard = machine().device<geneve_keyboard_device>(GKEYBOARD_TAG);
m_video = machine().device<bus8z_device>(VIDEO_SYSTEM_TAG); m_video = machine().device<bus8z_device>(VIDEO_SYSTEM_TAG);
m_sound = machine().device<bus8z_device>(TISOUND_TAG); m_sound = machine().device<bus8z_device>(TISOUND_TAG);
m_clock = machine().device(GCLOCK_TAG); m_clock = machine().device<mm58274c_device>(GCLOCK_TAG);
m_ready.resolve(conf->ready, *this); m_ready.resolve(conf->ready, *this);

View File

@ -13,6 +13,7 @@
#include "emu.h" #include "emu.h"
#include "ti99defs.h" #include "ti99defs.h"
#include "machine/mm58274c.h"
#include "video/v9938.h" #include "video/v9938.h"
extern const device_type GENEVE_MOUSE; extern const device_type GENEVE_MOUSE;
@ -180,7 +181,7 @@ private:
int m_waitcount; int m_waitcount;
// Devices // Devices
device_t* m_clock; mm58274c_device* m_clock;
geneve_keyboard_device* m_keyboard; geneve_keyboard_device* m_keyboard;
bus8z_device* m_video; bus8z_device* m_video;
bus8z_device* m_peribox; bus8z_device* m_peribox;

View File

@ -17,7 +17,6 @@
#include "hfdc.h" #include "hfdc.h"
#include "imagedev/flopdrv.h" #include "imagedev/flopdrv.h"
#include "machine/mm58274c.h"
#include "formats/ti99_dsk.h" // Format #include "formats/ti99_dsk.h" // Format
#define BUFFER "ram" #define BUFFER "ram"
@ -39,7 +38,9 @@
#define LOG logerror #define LOG logerror
myarc_hfdc_device::myarc_hfdc_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock) myarc_hfdc_device::myarc_hfdc_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock)
: ti_expansion_card_device(mconfig, TI99_HFDC, "Myarc Hard and Floppy Disk Controller", tag, owner, clock, "ti99_hfdc", __FILE__) : ti_expansion_card_device(mconfig, TI99_HFDC, "Myarc Hard and Floppy Disk Controller", tag, owner, clock, "ti99_hfdc", __FILE__),
m_hdc9234(*this, FDC_TAG),
m_clock(*this, CLOCK_TAG)
{ {
} }
@ -85,7 +86,7 @@ READ8Z_MEMBER(myarc_hfdc_device::readz)
if ((offset & 0x1fe1)==CLK_ADDR) if ((offset & 0x1fe1)==CLK_ADDR)
{ {
*value = mm58274c_r(m_clock, space, (offset & 0x001e) >> 1); *value = m_clock->read(space, (offset & 0x001e) >> 1);
if (VERBOSE>7) LOG("hfdc: read from clock address %04x: %02x\n", offset & 0xffff, *value); if (VERBOSE>7) LOG("hfdc: read from clock address %04x: %02x\n", offset & 0xffff, *value);
return; return;
} }
@ -139,7 +140,7 @@ WRITE8_MEMBER( myarc_hfdc_device::write )
if ((offset & 0x1fe1)==CLK_ADDR) if ((offset & 0x1fe1)==CLK_ADDR)
{ {
if (VERBOSE>7) LOG("hfdc: write to clock address %04x: %02x\n", offset & 0xffff, data); if (VERBOSE>7) LOG("hfdc: write to clock address %04x: %02x\n", offset & 0xffff, data);
mm58274c_w(m_clock, space, (offset & 0x001e) >> 1, data); m_clock->write(space, (offset & 0x001e) >> 1, data);
return; return;
} }
@ -495,8 +496,6 @@ INPUT_PORTS_END
void myarc_hfdc_device::device_start() void myarc_hfdc_device::device_start()
{ {
if (VERBOSE>5) LOG("hfdc: start\n"); if (VERBOSE>5) LOG("hfdc: start\n");
m_hdc9234 = static_cast<smc92x4_device *>(subdevice(FDC_TAG));
m_clock = subdevice(CLOCK_TAG);
m_dsrrom = memregion(DSRROM)->base(); m_dsrrom = memregion(DSRROM)->base();
m_buffer_ram = memregion(BUFFER)->base(); m_buffer_ram = memregion(BUFFER)->base();

View File

@ -17,6 +17,7 @@
#include "ti99defs.h" #include "ti99defs.h"
#include "ti99_hd.h" #include "ti99_hd.h"
#include "machine/smc92x4.h" #include "machine/smc92x4.h"
#include "machine/mm58274c.h"
#define HFDC_MAX_FLOPPY 4 #define HFDC_MAX_FLOPPY 4
#define HFDC_MAX_HARD 4 #define HFDC_MAX_HARD 4
@ -70,10 +71,10 @@ private:
// Link to the HDC9234 controller on the board. In fact, the proper name // Link to the HDC9234 controller on the board. In fact, the proper name
// is HDC 9234, the manufacturer is Standard Microsystems Corp. // is HDC 9234, the manufacturer is Standard Microsystems Corp.
smc92x4_device* m_hdc9234; required_device<smc92x4_device> m_hdc9234;
/* Link to the clock chip on the board. */ /* Link to the clock chip on the board. */
device_t* m_clock; required_device<mm58274c_device> m_clock;
/* Determines whether we have access to the CRU bits. */ /* Determines whether we have access to the CRU bits. */
bool m_cru_select; bool m_cru_select;