From e7517ea39e96383fd76d9965c43d1ba58321969d Mon Sep 17 00:00:00 2001 From: smf- Date: Fri, 1 Nov 2013 18:17:55 +0000 Subject: [PATCH] Fixed the MC146818 modernisation so that local/utc & whether a century is stored in nvram can be specified in a sane way. Removed the century updating as this chip doesn't do that, but each driver can specify where the century should be stored. Fixed off by one errors in the date/time updating. Added support for different external clock speeds and dividers, the clock speeds have been set based on guesswork that the code would set the chip to update at 1hz but this isn't necessarily true. Most flags have been implemented, so that timer updating can be disabled & irq generation should be correct. [smf] --- src/emu/bus/econet/e01.c | 3 +- src/emu/drivers/xtal.h | 1 + src/emu/machine/mc146818.c | 678 ++++++++++++++++++--------------- src/emu/machine/mc146818.h | 146 +++++-- src/mame/drivers/aristmk4.c | 2 +- src/mame/drivers/rastersp.c | 2 +- src/mame/machine/pcshare.c | 4 +- src/mess/drivers/amstr_pc.c | 2 +- src/mess/drivers/amstrad.c | 2 +- src/mess/drivers/at.c | 4 +- src/mess/drivers/bbc.c | 2 +- src/mess/drivers/bebox.c | 2 +- src/mess/drivers/hx20.c | 3 +- src/mess/drivers/mbee.c | 4 +- src/mess/drivers/micronic.c | 3 +- src/mess/drivers/nc.c | 2 +- src/mess/drivers/orion.c | 2 +- src/mess/drivers/pc1512.c | 7 +- src/mess/drivers/qx10.c | 3 +- src/mess/drivers/sgi_ip2.c | 2 +- src/mess/machine/apollo.c | 3 +- src/mess/machine/cs4031.c | 16 +- src/mess/machine/southbridge.c | 4 +- 23 files changed, 525 insertions(+), 372 deletions(-) diff --git a/src/emu/bus/econet/e01.c b/src/emu/bus/econet/e01.c index 86ea9b532cc..b48cdfbbe9b 100644 --- a/src/emu/bus/econet/e01.c +++ b/src/emu/bus/econet/e01.c @@ -296,7 +296,8 @@ static MACHINE_CONFIG_FRAGMENT( e01 ) MCFG_CPU_ADD(R65C102_TAG, M65C02, XTAL_8MHz/4) // Rockwell R65C102P3 MCFG_CPU_PROGRAM_MAP(e01_mem) - MCFG_MC146818_IRQ_ADD(HD146818_TAG, MC146818_STANDARD, WRITELINE(e01_device, rtc_irq_w)) + MCFG_MC146818_ADD(HD146818_TAG, XTAL_32_768kHz) + MCFG_MC146818_IRQ_HANDLER(WRITELINE(e01_device, rtc_irq_w)) // devices MCFG_VIA6522_ADD(R6522_TAG, XTAL_8MHz/4, via_intf) diff --git a/src/emu/drivers/xtal.h b/src/emu/drivers/xtal.h index c81f2539fd8..add860c0dcb 100644 --- a/src/emu/drivers/xtal.h +++ b/src/emu/drivers/xtal.h @@ -62,6 +62,7 @@ enum XTAL_4MHz = 4000000, XTAL_4_028MHz = 4028000, /* Sony SMC-777 */ XTAL_4_096MHz = 4096000, /* Used to drive OKI M9810 chips */ + XTAL_4_194304Mhz = 4194304, /* Used to drive MC146818 */ XTAL_4_224MHz = 4224000, /* Used to drive OKI M6295 chips, usually with /4 divider */ XTAL_4_41MHz = 4410000, /* Pioneer PR-8210 ldplayer */ XTAL_4_43361MHz = 4433610, /* Cidelsa Draco */ diff --git a/src/emu/machine/mc146818.c b/src/emu/machine/mc146818.c index 27ddcfb3b6d..a1b55916d79 100644 --- a/src/emu/machine/mc146818.c +++ b/src/emu/machine/mc146818.c @@ -4,74 +4,11 @@ Implementation of the MC146818 chip - Real time clock chip with battery backed ram (or CMOS) + Real time clock chip with CMOS battery backed ram Used in IBM PC/AT, several PC clones, Amstrad NC200, Apollo workstations - Nathan Woods (npwoods@mess.org) - Peter Trauner (peter.trauner@jk.uni-linz.ac.at) - - PC CMOS info (based on info from Padgett Peterson): - - Clock Related: - 0x00 Seconds (BCD 00-59, Hex 00-3B) Note: Bit 7 is read only - 0x01 Second Alarm (BCD 00-59, Hex 00-3B; "don't care" if C0-FF) - 0x02 Minutes (BCD 00-59, Hex 00-3B) - 0x03 Minute Alarm (BCD 00-59, Hex 00-3B; "don't care" if C0-FF)) - 0x04 Hours (BCD 00-23, Hex 00-17 if 24 hr mode) - (BCD 01-12, Hex 01-0C if 12 hr am) - (BCD 81-92. Hex 81-8C if 12 hr pm) - 0x05 Hour Alarm (same as hours; "don't care" if C0-FF)) - 0x06 Day of Week (01-07 Sunday=1) - 0x07 Date of Month (BCD 01-31, Hex 01-1F) - 0x08 Month (BCD 01-12, Hex 01-0C) - 0x09 Year (BCD 00-99, Hex 00-63) - 0x0B Status Register B (read/write) - Bit 7 - 1 enables cycle update, 0 disables - Bit 6 - 1 enables periodic interrupt - Bit 5 - 1 enables alarm interrupt - Bit 4 - 1 enables update-ended interrupt - Bit 3 - 1 enables square wave output - Bit 2 - Data Mode - 0: BCD, 1: Binary - Bit 1 - 24/12 hour selection - 1 enables 24 hour mode - Bit 0 - Daylight Savings Enable - 1 enables - 0x0C Status Register C (Read only) - Bit 7 - Interrupt request flag - 1 when any or all of bits 6-4 are - 1 and appropriate enables (Register B) are set to 1. Generates - IRQ 8 when triggered. - Bit 6 - Periodic Interrupt flag - Bit 5 - Alarm Interrupt flag - Bit 4 - Update-Ended Interrupt Flag - Bit 3-0 ??? - 0x0D Status Register D (read only) - Bit 7 - Valid RAM - 1 indicates batery power good, 0 if dead or - disconnected. - Bit 6-0 ??? - - Non-clock related: - 0x0E (PS/2) Diagnostic Status Byte - Bit 7 - When set (1) indicates clock has lost power - Bit 6 - (1) indicates incorrect checksum - Bit 5 - (1) indicates that equipment configuration is incorrect - power-on check requires that atleast one floppy be installed - Bit 4 - (1) indicates error in memory size - Bit 3 - (1) indicates that controller or disk drive failed initialization - Bit 2 - (1) indicates that time is invalid - Bit 1 - (1) indicates installed adaptors do not match configuration - Bit 0 - (1) indicates a time-out while reading adaptor ID - 0x0E (AMSTRAD) 6 BYTEs time and date machine last used - 0x0F Reset Code (IBM PS/2 "Shutdown Status Byte") - 0x00-0x03 perform power-on reset - 0x04 INT 19h reboot - 0x05 flush keyboard and jump via 0040:0067 - 0x06-0x07 reserved - 0x08 used by POST during protected-mode RAM test - 0x09 used for INT 15/87h (block move) support - 0x0A jump via 0040:0067 - 0x0B-0xFF perform power-on reset - *********************************************************************/ -#include "emu.h" #include "coreutil.h" #include "machine/mc146818.h" @@ -84,28 +21,6 @@ -//************************************************************************** -// MACROS -//************************************************************************** - -#define USE_UTC 1 - -#define HOURS_24 (m_data[0xb]&2) -#define BCD_MODE !(m_data[0xb]&4) // book has other description! -#define CENTURY m_data[72] -#define YEAR m_data[9] -#define MONTH m_data[8] -#define DAY m_data[7] -#define WEEK_DAY m_data[6] -#define HOUR m_data[4] -#define MINUTE m_data[2] -#define SECOND m_data[0] - - -//************************************************************************** -// LIVE DEVICE -//************************************************************************** - // device type definition const device_type MC146818 = &device_creator; @@ -115,29 +30,16 @@ const device_type MC146818 = &device_creator; mc146818_device::mc146818_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock) : device_t(mconfig, MC146818, "MC146818", tag, owner, clock, "mc146818", __FILE__), - device_rtc_interface(mconfig, *this), device_nvram_interface(mconfig, *this), - m_write_irq(*this), - m_type(MC146818_STANDARD), m_index(0), - m_eindex(0), - m_updated(false), - m_last_refresh(attotime::zero) + m_last_refresh(attotime::zero), + m_write_irq(*this), + m_century_index(-1), + m_use_utc(false) { } -//------------------------------------------------- -// static_set_interface - configuration helper -// to set the interface -//------------------------------------------------- - -void mc146818_device::static_set_type(device_t &device, mc146818_type type) -{ - downcast(device).m_type = type; -} - - //------------------------------------------------- // device_start - device-specific startup //------------------------------------------------- @@ -148,154 +50,115 @@ void mc146818_device::device_start() m_clock_timer = timer_alloc(TIMER_CLOCK); m_periodic_timer = timer_alloc(TIMER_PERIODIC); - memset(m_data, 0, sizeof(m_data)); - - m_clock_timer->adjust(attotime::from_hz(1), 0, attotime::from_hz(1)); - - m_periodic_timer->adjust(attotime::never); - m_period = attotime::never; - - set_base_datetime(); - m_write_irq.resolve_safe(); } +//------------------------------------------------- +// device_reset - device-specific reset +//------------------------------------------------- + +void mc146818_device::device_reset() +{ + m_data[REG_B] &= ~(REG_B_UIE | REG_B_AIE | REG_B_PIE | REG_B_SQWE); + m_data[REG_C] = 0; +} + //------------------------------------------------- // device_timer - handler timer events //------------------------------------------------- void mc146818_device::device_timer(emu_timer &timer, device_timer_id id, int param, void *ptr) { - int year/*, month*/; - - if (id == TIMER_PERIODIC) { - m_data[0x0c] |= 0xc0; - m_write_irq(CLEAR_LINE); - return; - } - - if (BCD_MODE) + switch (id) { - SECOND=bcd_adjust(SECOND+1); - if (SECOND>=0x60) + case TIMER_PERIODIC: + m_data[REG_C] |= REG_C_PF; + update_irq(); + break; + + case TIMER_CLOCK: + if (!(m_data[REG_B] & REG_B_SET)) { - SECOND=0; - MINUTE=bcd_adjust(MINUTE+1); - if (MINUTE>=0x60) + /// TODO: find out how the real chip deals with updates when binary/bcd values are already outside the normal range + int seconds = get_seconds() + 1; + if (seconds < 60) { - MINUTE=0; - HOUR=bcd_adjust(HOUR+1); - // different handling of hours - if (HOUR>=0x24) + set_seconds(seconds); + } + else + { + set_seconds(0); + + int minutes = get_minutes() + 1; + if (minutes < 60) { - HOUR=0; - WEEK_DAY=bcd_adjust(WEEK_DAY+1)%7; - DAY=bcd_adjust(DAY+1); - //month=bcd_2_dec(MONTH); - year=bcd_2_dec(YEAR); - if (m_type!=MC146818_IGNORE_CENTURY) year+=bcd_2_dec(CENTURY)*100; - else year+=2000; // save for julian_days_in_month calculation - DAY=bcd_adjust(DAY+1); - if (DAY>gregorian_days_in_month(MONTH, year)) + set_minutes(minutes); + } + else + { + set_minutes(0); + + int hours = get_hours() + 1; + if (hours < 24) { - DAY=1; - MONTH=bcd_adjust(MONTH+1); - if (MONTH>0x12) + set_hours(hours); + } + else + { + set_hours(0); + + int dayofweek = get_dayofweek() + 1; + if (dayofweek <= 7) { - MONTH=1; - YEAR=year=bcd_adjust(YEAR+1); - if (m_type!=MC146818_IGNORE_CENTURY) + set_dayofweek(dayofweek); + } + else + { + set_dayofweek(1); + } + + int dayofmonth = get_dayofmonth() + 1; + if (dayofmonth <= gregorian_days_in_month(get_month(), get_year() + 2000)) + { + set_dayofmonth(dayofmonth); + } + else + { + set_dayofmonth(1); + + int month = get_month() + 1; + if (month <= 12) { - if (year>=0x100) - { - CENTURY=bcd_adjust(CENTURY+1); - } + set_month(month); + } + else + { + set_month(1); + + set_year((get_year() + 1) % 100); } } } } } - } - } - else - { - SECOND=SECOND+1; - if (SECOND>=60) - { - SECOND=0; - MINUTE=MINUTE+1; - if (MINUTE>=60) { - MINUTE=0; - HOUR=HOUR+1; - // different handling of hours //? - if (HOUR>=24) { - HOUR=0; - WEEK_DAY=(WEEK_DAY+1)%7; - year=YEAR; - if (m_type!=MC146818_IGNORE_CENTURY) year+=CENTURY*100; - else year+=2000; // save for julian_days_in_month calculation - if (++DAY>gregorian_days_in_month(MONTH, year)) { - DAY=1; - if (++MONTH>12) { - MONTH=1; - YEAR++; - if (m_type!=MC146818_IGNORE_CENTURY) { - if (YEAR>=100) { CENTURY++;YEAR=0; } - } else { - YEAR%=100; - } - } - } - } + + if ((m_data[REG_ALARM_SECONDS] == m_data[REG_SECONDS] || (m_data[REG_ALARM_SECONDS] & ALARM_DONTCARE) == ALARM_DONTCARE) && + (m_data[REG_ALARM_MINUTES] == m_data[REG_MINUTES] || (m_data[REG_ALARM_MINUTES] & ALARM_DONTCARE) == ALARM_DONTCARE) && + (m_data[REG_ALARM_HOURS] == m_data[REG_HOURS] || (m_data[REG_ALARM_HOURS] & ALARM_DONTCARE) == ALARM_DONTCARE)) + { + // set the alarm interrupt flag AF + m_data[REG_C] |= REG_C_AF; } + + // set the update-ended interrupt Flag UF + m_data[REG_C] |= REG_C_UF; + update_irq(); + + m_last_refresh = machine().time(); } + break; } - - if (m_data[1] == SECOND && // - m_data[3] == MINUTE && // - m_data[5] == HOUR) { - // set the alarm interrupt flag AF - m_data[0x0c] |= 0x20; - } else { - // clear the alarm interrupt flag AF - m_data[0x0c] &= ~0x20; - if ((m_data[0x0c] & 0x70) == 0) { - // clear IRQF - m_data[0x0c] &= ~0x80; - } - } - - // set the update-ended interrupt Flag UF - m_data[0x0c] |= 0x10; - - // set the interrupt request flag IRQF - // FIXME: should throw IRQ line as well - if ((m_data[0x0b] & m_data[0x0c] & 0x30) != 0) { - m_data[0x0c] |= 0x80; - } - - // IRQ line is active low - m_write_irq((m_data[0x0c] & 0x80) ? CLEAR_LINE : ASSERT_LINE); - - m_updated = true; /* clock has been updated */ - m_last_refresh = machine().time(); -} - - -//------------------------------------------------- -// rtc_clock_updated - -//------------------------------------------------- - -void mc146818_device::rtc_clock_updated(int year, int month, int day, int day_of_week, int hour, int minute, int second) -{ - YEAR = year; - MONTH = month; - DAY = day; - WEEK_DAY = day_of_week; - HOUR = hour; - MINUTE = minute; - SECOND = second; } @@ -316,7 +179,14 @@ void mc146818_device::nvram_default() memcpy(m_data, m_region->base(), bytes); } + else + { + memset(m_data, 0, sizeof(m_data)); + } + set_base_datetime(); + update_timer(); + update_irq(); } @@ -328,7 +198,10 @@ void mc146818_device::nvram_default() void mc146818_device::nvram_read(emu_file &file) { file.read(m_data, sizeof(m_data)); + set_base_datetime(); + update_timer(); + update_irq(); } @@ -344,19 +217,144 @@ void mc146818_device::nvram_write(emu_file &file) //------------------------------------------------- -// dec_2_local - convert from decimal to BCD if -// necessary +// to_ram - convert value to current ram format //------------------------------------------------- -inline int mc146818_device::dec_2_local(int a) +int mc146818_device::to_ram(int a) { - return BCD_MODE ? dec_2_bcd(a) : a; + if (!(m_data[REG_B] & REG_B_DM)) + return dec_2_bcd(a); + + return a; } //------------------------------------------------- -// dec_2_local - convert from decimal to BCD if -// necessary +// from_ram - convert value from current ram format +//------------------------------------------------- + +int mc146818_device::from_ram(int a) +{ + if (!(m_data[REG_B] & REG_B_DM)) + return bcd_2_dec(a); + + return a; +} + + +int mc146818_device::get_seconds() +{ + return from_ram(m_data[REG_SECONDS]); +} + +void mc146818_device::set_seconds(int seconds) +{ + m_data[REG_SECONDS] = to_ram(seconds); +} + +int mc146818_device::get_minutes() +{ + return from_ram(m_data[REG_MINUTES]); +} + +void mc146818_device::set_minutes(int minutes) +{ + m_data[REG_MINUTES] = to_ram(minutes); +} + +int mc146818_device::get_hours() +{ + if (!(m_data[REG_B] & REG_B_24_12)) + { + int hours = from_ram(m_data[REG_HOURS] & ~HOURS_PM); + + if (hours == 12) + { + hours = 0; + } + + if (m_data[REG_HOURS] & HOURS_PM) + { + hours += 12; + } + + return hours; + } + else + { + return from_ram(m_data[REG_HOURS]); + } +} + +void mc146818_device::set_hours(int hours) +{ + if (!(m_data[REG_B] & REG_B_24_12)) + { + int pm = 0; + + if (hours >= 12) + { + hours -= 12; + pm = HOURS_PM; + } + + if (hours == 0) + { + hours = 12; + } + + m_data[REG_HOURS] = to_ram(hours) | pm; + } + else + { + m_data[REG_HOURS] = to_ram(hours); + } +} + +int mc146818_device::get_dayofweek() +{ + return from_ram(m_data[REG_DAYOFWEEK]); +} + +void mc146818_device::set_dayofweek(int dayofweek) +{ + m_data[REG_DAYOFWEEK] = to_ram(dayofweek); +} + +int mc146818_device::get_dayofmonth() +{ + return from_ram(m_data[REG_DAYOFMONTH]); +} + +void mc146818_device::set_dayofmonth(int dayofmonth) +{ + m_data[REG_DAYOFMONTH] = to_ram(dayofmonth); +} + +int mc146818_device::get_month() +{ + return from_ram(m_data[REG_MONTH]); +} + +void mc146818_device::set_month(int month) +{ + m_data[REG_MONTH] = to_ram(month); +} + +int mc146818_device::get_year() +{ + return from_ram(m_data[REG_YEAR]); +} + +void mc146818_device::set_year(int year) +{ + m_data[REG_YEAR] = to_ram(year); +} + + + +//------------------------------------------------- +// set_base_datetime - update clock with real time //------------------------------------------------- void mc146818_device::set_base_datetime() @@ -366,34 +364,117 @@ void mc146818_device::set_base_datetime() machine().base_datetime(systime); - current_time = (m_type == MC146818_UTC) ? systime.utc_time: systime.local_time; + current_time = (m_use_utc) ? systime.utc_time: systime.local_time; // logerror("mc146818_set_base_datetime %02d/%02d/%02d %02d:%02d:%02d\n", // current_time.year % 100, current_time.month + 1, current_time.mday, // current_time.hour,current_time.minute, current_time.second); - if (HOURS_24 || (current_time.hour < 12)) - HOUR = dec_2_local(current_time.hour); - else - HOUR = dec_2_local(current_time.hour - 12) | 0x80; + set_seconds(current_time.second); + set_minutes(current_time.minute); + set_hours(current_time.hour); + set_dayofweek(current_time.weekday + 1); + set_dayofmonth(current_time.mday); + set_month(current_time.month + 1); + set_year(current_time.year % 100); - if (m_type != MC146818_IGNORE_CENTURY) - CENTURY = dec_2_local(current_time.year /100); - - SECOND = dec_2_local(current_time.second); - MINUTE = dec_2_local(current_time.minute); - DAY = dec_2_local(current_time.mday); - MONTH = dec_2_local(current_time.month + 1); - YEAR = dec_2_local(current_time.year % 100); - - WEEK_DAY = current_time.weekday; - if (current_time.is_dst) - m_data[0xb] |= 1; - else - m_data[0xb] &= ~1; + if (m_century_index >= 0) + m_data[m_century_index] = to_ram(current_time.year / 100); } +//------------------------------------------------- +// update_timer - update timer based on A register +//------------------------------------------------- + +void mc146818_device::update_timer() +{ + int bypass; + + switch (m_data[REG_A] & (REG_A_DV2 | REG_A_DV1 | REG_A_DV0)) + { + case 0: + bypass = 0; + break; + + case REG_A_DV0: + bypass = 2; + break; + + case REG_A_DV1: + bypass = 7; + break; + + case REG_A_DV2 | REG_A_DV1: + case REG_A_DV2 | REG_A_DV1 | REG_A_DV0: + bypass = 22; + break; + + default: + // TODO: other combinations of divider bits are used for test purposes only + bypass = 22; + break; + } + + + attotime update_period = attotime::never; + attotime update_interval = attotime::never; + attotime periodic_period = attotime::never; + attotime periodic_interval = attotime::never; + + if (bypass < 22) + { + int shift = 22 - bypass; + + double update_hz = (double) clock() / (1 << shift); + + // TODO: take the time since last timer into account + update_period = attotime::from_hz(update_hz * 2); + update_interval = attotime::from_hz(update_hz); + + int rate_select = m_data[REG_A] & (REG_A_RS3 | REG_A_RS2 | REG_A_RS1 | REG_A_RS0); + if (rate_select != 0) + { + shift = (rate_select + 6) - bypass; + if (shift <= 1) + shift += 7; + + double periodic_hz = (double) clock() / (1 << shift); + + // TODO: take the time since last timer into account + periodic_period = attotime::from_hz(periodic_hz * 2); + periodic_interval = attotime::from_hz(periodic_hz); + } + } + + m_clock_timer->adjust(update_period, 0, update_interval); + m_periodic_timer->adjust(periodic_period, 0, periodic_interval); +} + + +//------------------------------------------------- +// update_irq - Update irq based on B & C register +//------------------------------------------------- + +void mc146818_device::update_irq() +{ + // IRQ line is active low + if (((m_data[REG_C] & REG_C_UF) && (m_data[REG_B] & REG_B_UIE)) || + ((m_data[REG_C] & REG_C_AF) && (m_data[REG_B] & REG_B_AIE)) || + ((m_data[REG_C] & REG_C_PF) && (m_data[REG_B] & REG_B_PIE))) + { + m_data[REG_C] |= REG_C_IRQF; + m_write_irq(CLEAR_LINE); + } + else + { + m_data[REG_C] &= REG_C_IRQF; + m_write_irq(ASSERT_LINE); + } +} + + + //------------------------------------------------- // read - I/O handler for reading //------------------------------------------------- @@ -401,42 +482,38 @@ void mc146818_device::set_base_datetime() READ8_MEMBER( mc146818_device::read ) { UINT8 data = 0; - switch (offset) { + switch (offset) + { case 0: data = m_index; break; case 1: - switch (m_index % MC146818_DATA_SIZE) { - case 0xa: - data = m_data[m_index % MC146818_DATA_SIZE]; + switch (m_index) + { + case REG_A: + data = m_data[REG_A]; // Update In Progress (UIP) time for 32768 Hz is 244+1984usec + /// TODO: support other dividers if ((space.machine().time() - m_last_refresh) < attotime::from_usec(244+1984)) - data |= 0x80; -#if 0 - /* for pc1512 bios realtime clock test */ - m_data[m_index % MC146818_DATA_SIZE] ^= 0x80; /* 0x80 update in progress */ -#endif + data |= REG_A_UIP; break; - case 0xc: -// if(m_updated) /* the clock has been updated */ -// data = 0x10; -// else -// data = 0x00; + case REG_C: // the unused bits b0 ... b3 are always read as 0 - data = m_data[m_index % MC146818_DATA_SIZE] & 0xf0; + data = m_data[REG_C] & (REG_C_IRQF | REG_C_PF | REG_C_AF | REG_C_UF); // read 0x0c will clear all IRQ flags in register 0x0c - m_data[m_index % MC146818_DATA_SIZE] &= 0x0f; - m_write_irq(ASSERT_LINE); + m_data[REG_C] &= ~(REG_C_IRQF | REG_C_PF | REG_C_AF | REG_C_UF); + update_irq(); break; - case 0xd: + + case REG_D: /* battery ok */ - data = m_data[m_index % MC146818_DATA_SIZE] | 0x80; + data = m_data[REG_D] | REG_D_VRT; break; default: - data = m_data[m_index % MC146818_DATA_SIZE]; + data = m_data[m_index]; break; } break; @@ -444,6 +521,7 @@ READ8_MEMBER( mc146818_device::read ) if (LOG_MC146818) logerror("mc146818_port_r(): index=0x%02x data=0x%02x\n", m_index, data); + return data; } @@ -454,51 +532,45 @@ READ8_MEMBER( mc146818_device::read ) WRITE8_MEMBER( mc146818_device::write ) { - attotime rate; if (LOG_MC146818) logerror("mc146818_port_w(): index=0x%02x data=0x%02x\n", m_index, data); - switch (offset) { + switch (offset) + { case 0: - m_index = data; + m_index = data % MC146818_DATA_SIZE; break; case 1: - switch(m_index % MC146818_DATA_SIZE) + switch (m_index) { - case 0x0a: - // fixme: allow different time base - data &= 0x0f; - if (data > 2) - m_period = attotime::from_hz(32768 >> (data - 1)); - else if (data > 0) - m_period = attotime::from_hz(32768 >> (data + 6)); - else m_period = attotime::never; + case REG_SECONDS: + // top bit of SECONDS is read only + m_data[REG_SECONDS] = data & ~0x80; + break; - if(m_data[0x0b] & 0x40) - rate = attotime::zero; - else rate = attotime::never; + case REG_A: + // top bit of A is read only + m_data[REG_A] = data & ~REG_A_UIP; + update_timer(); + break; - m_periodic_timer->adjust(rate, 0, m_period); - data |= m_data[m_index % MC146818_DATA_SIZE] & 0xf0; - m_data[m_index % MC146818_DATA_SIZE] = data; + case REG_B: + if ((data & REG_B_SET) && !(m_data[REG_B] & REG_B_SET)) + data &= ~REG_B_UIE; + + m_data[REG_B] = data; + update_irq(); break; - case 0x0b: - if(data & 0x80) - m_updated = false; - // this probably isn't right but otherwise - // you'll be making a lot of unnecessary callbacks - if (data & 0x40) - m_periodic_timer->adjust(attotime::zero, 0, m_period); - else - m_periodic_timer->adjust(attotime::never); - m_data[m_index % MC146818_DATA_SIZE] = data; - break; - case 0x0c: - // register 0x0c is readonly + + case REG_C: + case REG_D: + // register C & D is readonly break; + default: - m_data[m_index % MC146818_DATA_SIZE] = data; + m_data[m_index] = data; + break; } break; } diff --git a/src/emu/machine/mc146818.h b/src/emu/machine/mc146818.h index 3d8a4ac9261..51826e014bb 100644 --- a/src/emu/machine/mc146818.h +++ b/src/emu/machine/mc146818.h @@ -4,29 +4,33 @@ Implementation of the MC146818 chip - Real time clock chip with battery backed ram - Used in IBM PC/AT, several PC clones, Amstrad NC200 - - Peter Trauner (peter.trauner@jk.uni-linz.ac.at) + Real time clock chip with CMOS battery backed ram + Used in IBM PC/AT, several PC clones, Amstrad NC200, Apollo workstations *********************************************************************/ #ifndef __MC146818_H__ #define __MC146818_H__ +#include "emu.h" //************************************************************************** // INTERFACE CONFIGURATION MACROS //************************************************************************** -#define MCFG_MC146818_IRQ_ADD(_tag, _type, _irq) \ - MCFG_DEVICE_ADD(_tag, MC146818, 0) \ - mc146818_device::static_set_type(*device, mc146818_device::_type); \ +#define MCFG_MC146818_ADD(_tag, _xtal) \ + MCFG_DEVICE_ADD(_tag, MC146818, _xtal) + +#define MCFG_MC146818_IRQ_HANDLER(_irq) \ downcast(device)->set_irq_callback(DEVCB2_##_irq); -#define MCFG_MC146818_ADD(_tag, _type) \ - MCFG_DEVICE_ADD(_tag, MC146818, 0) \ - mc146818_device::static_set_type(*device, mc146818_device::_type); +// The MC146818 doesn't have century support, but when syncing the date & time at startup we can optionally store the century. +#define MCFG_MC146818_CENTURY_INDEX(_century_index) \ + downcast(device)->set_century_index(_century_index); + +// The MC146818 doesn't have UTC support, but when syncing the data & time at startup we can use UTC instead of local time. +#define MCFG_MC146818_UTC(_utc) \ + downcast(device)->set_use_utc(_utc); //************************************************************************** // TYPE DEFINITIONS @@ -35,76 +39,134 @@ // ======================> mc146818_device class mc146818_device : public device_t, - public device_rtc_interface, public device_nvram_interface { public: - // values - enum mc146818_type - { - MC146818_STANDARD, - MC146818_IGNORE_CENTURY, // century is NOT set, for systems having other usage of this byte - MC146818_ENHANCED, - MC146818_UTC - }; - // construction/destruction mc146818_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock); - // inline configuration helpers - static void static_set_type(device_t &device, mc146818_type type); - // callbacks template void set_irq_callback(_irq irq) { m_write_irq.set_callback(irq); } + void set_century_index(int century_index) { m_century_index = century_index; } + void set_use_utc(bool use_utc) { m_use_utc = use_utc; } // read/write access DECLARE_READ8_MEMBER( read ); DECLARE_WRITE8_MEMBER( write ); - DECLARE_WRITE8_MEMBER( address_w ) { write(space, 0, data); } - DECLARE_READ8_MEMBER( data_r ) { return read(space, 1); } - DECLARE_WRITE8_MEMBER( data_w ) { write(space, 1, data); } - protected: // device-level overrides virtual void device_start(); + virtual void device_reset(); virtual void device_timer(emu_timer &timer, device_timer_id id, int param, void *ptr); - // device_rtc_interface overrides - virtual void rtc_clock_updated(int year, int month, int day, int day_of_week, int hour, int minute, int second); - // device_nvram_interface overrides virtual void nvram_default(); virtual void nvram_read(emu_file &file); virtual void nvram_write(emu_file &file); - // internal helpers - int dec_2_local(int a); - void set_base_datetime(); + static const unsigned char ALARM_DONTCARE = 0xc0; + static const unsigned char HOURS_PM = 0x80; - devcb2_write_line m_write_irq; +private: + enum + { + REG_SECONDS = 0, + REG_ALARM_SECONDS = 1, + REG_MINUTES = 2, + REG_ALARM_MINUTES = 3, + REG_HOURS = 4, + REG_ALARM_HOURS = 5, + REG_DAYOFWEEK = 6, + REG_DAYOFMONTH = 7, + REG_MONTH = 8, + REG_YEAR = 9, + REG_A = 0xa, + REG_B = 0xb, + REG_C = 0xc, + REG_D = 0xd + }; + + enum + { + REG_A_RS0 = 1, + REG_A_RS1 = 2, + REG_A_RS2 = 4, + REG_A_RS3 = 8, + REG_A_DV0 = 16, + REG_A_DV1 = 32, + REG_A_DV2 = 64, + REG_A_UIP = 128 + }; + + enum + { + REG_B_DSE = 1, // TODO: When set the chip will adjust the clock by an hour at start and end of DST + REG_B_24_12 = 2, + REG_B_DM = 4, + REG_B_SQWE = 8, // TODO: When set the chip will output a square wave on SQW pin + REG_B_UIE = 16, + REG_B_AIE = 32, + REG_B_PIE = 64, + REG_B_SET = 128, + }; + + enum + { + REG_C_UF = 16, + REG_C_AF = 32, + REG_C_PF = 64, + REG_C_IRQF = 128 + }; + + enum + { + REG_D_VRT = 128 + }; + + // internal helpers + int to_ram(int a); + int from_ram(int a); + void set_base_datetime(); + void update_irq(); + void update_timer(); + + int get_seconds(); + void set_seconds(int seconds); + int get_minutes(); + void set_minutes(int minutes); + int get_hours(); + void set_hours(int hours); + int get_dayofweek(); + void set_dayofweek(int dayofweek); + int get_dayofmonth(); + void set_dayofmonth(int dayofmonth); + int get_month(); + void set_month(int month); + int get_year(); + void set_year(int year); // internal state - static const int MC146818_DATA_SIZE = 0x80; - mc146818_type m_type; + // TODO: MC146818 only has 64 bytes, but semi-compatible chips have more. + // drivers are using this device when the actual hardware uses a different + // chip (which in most cases also has additional functionality). + static const int MC146818_DATA_SIZE = 128; UINT8 m_index; UINT8 m_data[MC146818_DATA_SIZE]; - UINT16 m_eindex; - UINT8 m_edata[0x2000]; - - bool m_updated; /* update ended interrupt flag */ - attotime m_last_refresh; - attotime m_period; static const device_timer_id TIMER_CLOCK = 0; static const device_timer_id TIMER_PERIODIC = 1; emu_timer *m_clock_timer; emu_timer *m_periodic_timer; + + devcb2_write_line m_write_irq; + int m_century_index; + bool m_use_utc; }; diff --git a/src/mame/drivers/aristmk4.c b/src/mame/drivers/aristmk4.c index ebe3c633050..f29d1ea65f4 100644 --- a/src/mame/drivers/aristmk4.c +++ b/src/mame/drivers/aristmk4.c @@ -1709,7 +1709,7 @@ static MACHINE_CONFIG_START( aristmk4, aristmk4_state ) MCFG_VIA6522_ADD("via6522_0", 0, via_interface) /* 1 MHz.(only 1 or 2 MHz.are valid) */ MCFG_PIA6821_ADD("pia6821_0", aristmk4_pia1_intf) MCFG_MC6845_ADD("crtc", C6545_1, "screen", MAIN_CLOCK/8, mc6845_intf) // TODO: type is unknown - MCFG_MC146818_ADD("rtc", MC146818_IGNORE_CENTURY) + MCFG_MC146818_ADD( "rtc", XTAL_4_194304Mhz ) MCFG_SPEAKER_STANDARD_MONO("mono") diff --git a/src/mame/drivers/rastersp.c b/src/mame/drivers/rastersp.c index 3cb5496c09f..1b511fb5bad 100644 --- a/src/mame/drivers/rastersp.c +++ b/src/mame/drivers/rastersp.c @@ -891,7 +891,7 @@ static MACHINE_CONFIG_START( rastersp, rastersp_state ) /* Devices */ MCFG_TIMER_DRIVER_ADD("tms_timer1", rastersp_state, tms_timer1) MCFG_TIMER_DRIVER_ADD("tms_tx_timer", rastersp_state, tms_tx_timer) - MCFG_MC146818_ADD("rtc", MC146818_STANDARD) + MCFG_MC146818_ADD( "rtc", XTAL_32_768kHz ) MCFG_NVRAM_HANDLER(rastersp) MCFG_NSCSI_BUS_ADD("scsibus") diff --git a/src/mame/machine/pcshare.c b/src/mame/machine/pcshare.c index 46501bb51c4..3f2fd7ea0ae 100644 --- a/src/mame/machine/pcshare.c +++ b/src/mame/machine/pcshare.c @@ -228,7 +228,9 @@ MACHINE_CONFIG_FRAGMENT(pcat_common) MCFG_I8237_ADD( "dma8237_1", XTAL_14_31818MHz/3, dma8237_1_config ) MCFG_I8237_ADD( "dma8237_2", XTAL_14_31818MHz/3, dma8237_2_config ) MCFG_PIT8254_ADD( "pit8254", at_pit8254_config ) - MCFG_MC146818_IRQ_ADD("rtc", MC146818_STANDARD, DEVWRITELINE("pic8259_2", pic8259_device, ir0_w)) + MCFG_MC146818_ADD("rtc", XTAL_32_768kHz) + MCFG_MC146818_IRQ_HANDLER(DEVWRITELINE("pic8259_2", pic8259_device, ir0_w)) + MCFG_MC146818_CENTURY_INDEX(0x32) MCFG_KBDC8042_ADD("kbdc", at8042) MACHINE_CONFIG_END diff --git a/src/mess/drivers/amstr_pc.c b/src/mess/drivers/amstr_pc.c index fdda1894d87..bcf36c054fb 100644 --- a/src/mess/drivers/amstr_pc.c +++ b/src/mess/drivers/amstr_pc.c @@ -372,7 +372,7 @@ static MACHINE_CONFIG_START( ppc512, amstrad_pc_state ) MCFG_FLOPPY_DRIVE_ADD("fdc:0", ibmpc_floppies, "525dd", ibmpc_floppy_formats) MCFG_FLOPPY_DRIVE_ADD("fdc:1", ibmpc_floppies, "525dd", ibmpc_floppy_formats) - MCFG_MC146818_ADD( "rtc", MC146818_IGNORE_CENTURY ) + MCFG_MC146818_ADD( "rtc", XTAL_32_768kHz ) /* internal ram */ MCFG_RAM_ADD(RAM_TAG) diff --git a/src/mess/drivers/amstrad.c b/src/mess/drivers/amstrad.c index 9ad04e87db5..b1c2f868707 100644 --- a/src/mess/drivers/amstrad.c +++ b/src/mess/drivers/amstrad.c @@ -1016,7 +1016,7 @@ static MACHINE_CONFIG_DERIVED( aleste, amstrad ) MCFG_SOUND_ROUTE(ALL_OUTPUTS, "mono", 0.25) MCFG_PALETTE_LENGTH(32+64) MCFG_PALETTE_INIT_OVERRIDE(amstrad_state,aleste) - MCFG_MC146818_ADD( "rtc", MC146818_IGNORE_CENTURY ) + MCFG_MC146818_ADD( "rtc", XTAL_4_194304Mhz ) MCFG_DEVICE_REMOVE("upd765") MCFG_I8272A_ADD("upd765", true) diff --git a/src/mess/drivers/at.c b/src/mess/drivers/at.c index a2436357282..d374ab12417 100644 --- a/src/mess/drivers/at.c +++ b/src/mess/drivers/at.c @@ -339,7 +339,9 @@ static MACHINE_CONFIG_FRAGMENT( at_motherboard ) MCFG_AT_KEYBOARD_CONTROLLER_ADD("keybc", XTAL_12MHz, keyboard_controller_intf) MCFG_PC_KBDC_ADD("pc_kbdc", pc_kbdc_intf) - MCFG_MC146818_IRQ_ADD( "rtc", MC146818_STANDARD, WRITELINE(at_state, at_mc146818_irq)) + MCFG_MC146818_ADD( "rtc", XTAL_32_768kHz ) + MCFG_MC146818_IRQ_HANDLER(WRITELINE(at_state, at_mc146818_irq)) + MCFG_MC146818_CENTURY_INDEX(0x32) /* sound hardware */ MCFG_SPEAKER_STANDARD_MONO("mono") diff --git a/src/mess/drivers/bbc.c b/src/mess/drivers/bbc.c index 20919e193e1..1bcd663077c 100644 --- a/src/mess/drivers/bbc.c +++ b/src/mess/drivers/bbc.c @@ -872,7 +872,7 @@ static MACHINE_CONFIG_START( bbcm, bbc_state ) MCFG_SOUND_ROUTE(ALL_OUTPUTS, "mono", 1.00) /* rtc and cmos */ - MCFG_MC146818_ADD( "rtc", MC146818_IGNORE_CENTURY ) + MCFG_MC146818_ADD( "rtc", XTAL_32_768kHz ) /* printer */ MCFG_CENTRONICS_PRINTER_ADD("centronics", bbcb_centronics_config) diff --git a/src/mess/drivers/bebox.c b/src/mess/drivers/bebox.c index 2281a875637..e6decea4f4f 100644 --- a/src/mess/drivers/bebox.c +++ b/src/mess/drivers/bebox.c @@ -233,7 +233,7 @@ static MACHINE_CONFIG_START( bebox, bebox_state ) MCFG_SMC37C78_ADD("smc37c78") MCFG_FLOPPY_DRIVE_ADD("smc37c78:0", bebox_floppies, "35hd", bebox_state::floppy_formats) - MCFG_MC146818_ADD( "rtc", MC146818_STANDARD ) + MCFG_MC146818_ADD( "rtc", XTAL_32_768kHz ) MCFG_KBDC8042_ADD("kbdc", bebox_8042_interface) /* internal ram */ diff --git a/src/mess/drivers/hx20.c b/src/mess/drivers/hx20.c index 09c002c21b3..2164efadfda 100644 --- a/src/mess/drivers/hx20.c +++ b/src/mess/drivers/hx20.c @@ -860,7 +860,8 @@ static MACHINE_CONFIG_START( hx20, hx20_state ) MCFG_SOUND_ROUTE(ALL_OUTPUTS, "mono", 0.25) // devices - MCFG_MC146818_IRQ_ADD(MC146818_TAG, MC146818_STANDARD, WRITELINE(hx20_state, rtc_irq_w)) + MCFG_MC146818_ADD(MC146818_TAG, XTAL_4_194304Mhz) + MCFG_MC146818_IRQ_HANDLER(WRITELINE(hx20_state, rtc_irq_w)) MCFG_RS232_PORT_ADD(RS232_TAG, rs232_intf, default_rs232_devices, NULL) MCFG_CASSETTE_ADD(CASSETTE_TAG, default_cassette_interface) MCFG_EPSON_SIO_ADD("sio", "tf20") diff --git a/src/mess/drivers/mbee.c b/src/mess/drivers/mbee.c index 057e93e91f2..d35634cef16 100644 --- a/src/mess/drivers/mbee.c +++ b/src/mess/drivers/mbee.c @@ -855,7 +855,7 @@ static MACHINE_CONFIG_DERIVED( mbee256, mbee128 ) MCFG_CPU_MODIFY( "maincpu" ) MCFG_CPU_IO_MAP(mbee256_io) MCFG_MACHINE_RESET_OVERRIDE(mbee_state, mbee256 ) - MCFG_MC146818_ADD( "rtc", MC146818_STANDARD ) + MCFG_MC146818_ADD( "rtc", XTAL_32_768kHz ) MCFG_DEVICE_REMOVE("crtc") MCFG_MC6845_ADD("crtc", SY6545_1, "screen", XTAL_13_5MHz / 8, mbee256_crtc) MACHINE_CONFIG_END @@ -865,7 +865,7 @@ static MACHINE_CONFIG_DERIVED( mbeett, mbeeppc ) MCFG_CPU_PROGRAM_MAP(mbeett_mem) MCFG_CPU_IO_MAP(mbeett_io) MCFG_MACHINE_RESET_OVERRIDE(mbee_state, mbeett ) - MCFG_MC146818_ADD( "rtc", MC146818_STANDARD ) + MCFG_MC146818_ADD( "rtc", XTAL_32_768kHz ) MCFG_DEVICE_REMOVE("crtc") MCFG_MC6845_ADD("crtc", SY6545_1, "screen", XTAL_13_5MHz / 8, mbee256_crtc) MACHINE_CONFIG_END diff --git a/src/mess/drivers/micronic.c b/src/mess/drivers/micronic.c index e35cf3071a5..a948d6d514a 100644 --- a/src/mess/drivers/micronic.c +++ b/src/mess/drivers/micronic.c @@ -391,7 +391,8 @@ static MACHINE_CONFIG_START( micronic, micronic_state ) MCFG_NVRAM_HANDLER(micronic) - MCFG_MC146818_IRQ_ADD( MC146818_TAG, MC146818_IGNORE_CENTURY, WRITELINE(micronic_state, mc146818_irq)) + MCFG_MC146818_ADD( MC146818_TAG, XTAL_4_194304Mhz ) + MCFG_MC146818_IRQ_HANDLER(WRITELINE(micronic_state, mc146818_irq)) MACHINE_CONFIG_END /* ROM definition */ diff --git a/src/mess/drivers/nc.c b/src/mess/drivers/nc.c index 993e9e90094..5ffe280b333 100644 --- a/src/mess/drivers/nc.c +++ b/src/mess/drivers/nc.c @@ -1644,7 +1644,7 @@ static MACHINE_CONFIG_DERIVED( nc200, nc100 ) MCFG_FLOPPY_DRIVE_ADD("upd765:0", ibmpc_floppies, "525dd", ibmpc_floppy_formats) MCFG_FLOPPY_DRIVE_ADD("upd765:1", ibmpc_floppies, "525dd", ibmpc_floppy_formats) - MCFG_MC146818_ADD( "mc", MC146818_STANDARD ) + MCFG_MC146818_ADD( "mc", XTAL_4_194304Mhz ) /* internal ram */ MCFG_RAM_MODIFY(RAM_TAG) diff --git a/src/mess/drivers/orion.c b/src/mess/drivers/orion.c index 29846381191..9383b60b5e4 100644 --- a/src/mess/drivers/orion.c +++ b/src/mess/drivers/orion.c @@ -179,7 +179,7 @@ static MACHINE_CONFIG_START( orionz80, orion_state ) MCFG_VIDEO_START_OVERRIDE(orion_state,orion128) - MCFG_MC146818_ADD( "rtc", MC146818_IGNORE_CENTURY ) + MCFG_MC146818_ADD( "rtc", XTAL_4_194304Mhz ) MCFG_SPEAKER_STANDARD_MONO("mono") MCFG_SOUND_ADD("speaker", SPEAKER_SOUND, 0) diff --git a/src/mess/drivers/pc1512.c b/src/mess/drivers/pc1512.c index 87867936ec2..5f16e535ff5 100644 --- a/src/mess/drivers/pc1512.c +++ b/src/mess/drivers/pc1512.c @@ -14,7 +14,6 @@ TODO: - adjust mouse speed - - RTC should not be y2k compliant - pc1512 V3 VDU check fails - Amstrad SM2400 internal modem - Amstrad RP4 diagnostic ISA card (PC1512) @@ -1305,7 +1304,8 @@ static MACHINE_CONFIG_START( pc1512, pc1512_state ) MCFG_I8237_ADD(I8237A5_TAG, XTAL_24MHz/6, dmac_intf) MCFG_PIC8259_ADD(I8259A2_TAG, INPUTLINE(I8086_TAG, INPUT_LINE_IRQ0), VCC, NULL) MCFG_PIT8253_ADD(I8253_TAG, pit_intf) - MCFG_MC146818_IRQ_ADD(MC146818_TAG, MC146818_STANDARD, DEVWRITELINE(I8259A2_TAG, pic8259_device, ir2_w)) + MCFG_MC146818_ADD(MC146818_TAG, XTAL_32_768kHz) + MCFG_MC146818_IRQ_HANDLER(DEVWRITELINE(I8259A2_TAG, pic8259_device, ir2_w)) MCFG_PC_FDC_XT_ADD(PC_FDC_XT_TAG) MCFG_FLOPPY_DRIVE_ADD(PC_FDC_XT_TAG ":0", pc1512_floppies, "525dd", pc1512_state::floppy_formats) MCFG_FLOPPY_DRIVE_ADD(PC_FDC_XT_TAG ":1", pc1512_floppies, NULL, pc1512_state::floppy_formats) @@ -1368,7 +1368,8 @@ static MACHINE_CONFIG_START( pc1640, pc1640_state ) MCFG_I8237_ADD(I8237A5_TAG, XTAL_24MHz/6, dmac_intf) MCFG_PIC8259_ADD(I8259A2_TAG, INPUTLINE(I8086_TAG, INPUT_LINE_IRQ0), VCC, NULL) MCFG_PIT8253_ADD(I8253_TAG, pit_intf) - MCFG_MC146818_IRQ_ADD(MC146818_TAG, MC146818_STANDARD, DEVWRITELINE(I8259A2_TAG, pic8259_device, ir2_w)) + MCFG_MC146818_ADD(MC146818_TAG, XTAL_32_768kHz) + MCFG_MC146818_IRQ_HANDLER(DEVWRITELINE(I8259A2_TAG, pic8259_device, ir2_w)) MCFG_PC_FDC_XT_ADD(PC_FDC_XT_TAG) MCFG_FLOPPY_DRIVE_ADD(PC_FDC_XT_TAG ":0", pc1512_floppies, "525dd", pc1512_state::floppy_formats) MCFG_FLOPPY_DRIVE_ADD(PC_FDC_XT_TAG ":1", pc1512_floppies, NULL, pc1512_state::floppy_formats) diff --git a/src/mess/drivers/qx10.c b/src/mess/drivers/qx10.c index 901e627e40a..f78f617de3b 100644 --- a/src/mess/drivers/qx10.c +++ b/src/mess/drivers/qx10.c @@ -882,7 +882,8 @@ static MACHINE_CONFIG_START( qx10, qx10_state ) MCFG_I8237_ADD("8237dma_1", MAIN_CLK/4, qx10_dma8237_1_interface) MCFG_I8237_ADD("8237dma_2", MAIN_CLK/4, qx10_dma8237_2_interface) MCFG_UPD7220_ADD("upd7220", MAIN_CLK/6, hgdc_intf, upd7220_map) // unk clock - MCFG_MC146818_IRQ_ADD( "rtc", MC146818_STANDARD, DEVWRITELINE("pic8259_slave", pic8259_device, ir2_w)) + MCFG_MC146818_ADD( "rtc", XTAL_32_768kHz ) + MCFG_MC146818_IRQ_HANDLER(DEVWRITELINE("pic8259_slave", pic8259_device, ir2_w)) MCFG_UPD765A_ADD("upd765", true, true) MCFG_FLOPPY_DRIVE_ADD("upd765:0", qx10_floppies, "525dd", floppy_image_device::default_floppy_formats) MCFG_FLOPPY_DRIVE_ADD("upd765:1", qx10_floppies, "525dd", floppy_image_device::default_floppy_formats) diff --git a/src/mess/drivers/sgi_ip2.c b/src/mess/drivers/sgi_ip2.c index 9be0ded2e5a..14a256896c2 100644 --- a/src/mess/drivers/sgi_ip2.c +++ b/src/mess/drivers/sgi_ip2.c @@ -490,7 +490,7 @@ static MACHINE_CONFIG_START( sgi_ip2, sgi_ip2_state ) MCFG_DUART68681_ADD( "duart68681a", XTAL_3_6864MHz, sgi_ip2_duart68681a_config ) /* Y3 3.6864MHz Xtal ??? copy-over from dectalk */ MCFG_DUART68681_ADD( "duart68681b", XTAL_3_6864MHz, sgi_ip2_duart68681b_config ) /* Y3 3.6864MHz Xtal ??? copy-over from dectalk */ - MCFG_MC146818_ADD( "rtc", MC146818_IGNORE_CENTURY ) + MCFG_MC146818_ADD( "rtc", XTAL_4_194304Mhz ) /* sound hardware */ MCFG_SPEAKER_STANDARD_MONO("mono") diff --git a/src/mess/machine/apollo.c b/src/mess/machine/apollo.c index c38a1f7c882..93fa7a4563f 100644 --- a/src/mess/machine/apollo.c +++ b/src/mess/machine/apollo.c @@ -1394,7 +1394,8 @@ MACHINE_CONFIG_FRAGMENT( apollo ) MCFG_PIC8259_ADD( APOLLO_PIC2_TAG, WRITELINE(apollo_state,apollo_pic8259_slave_set_int_line), GND, NULL) MCFG_PTM6840_ADD(APOLLO_PTM_TAG, apollo_ptm_config) - MCFG_MC146818_ADD( APOLLO_RTC_TAG, MC146818_UTC ) + MCFG_MC146818_ADD( APOLLO_RTC_TAG, XTAL_4_194304Mhz ) + MCFG_MC146818_UTC( true ) MCFG_DUART68681_ADD( APOLLO_SIO_TAG, XTAL_3_6864MHz, apollo_sio_config ) MCFG_DUART68681_ADD( APOLLO_SIO2_TAG, XTAL_3_6864MHz, apollo_sio2_config ) diff --git a/src/mess/machine/cs4031.c b/src/mess/machine/cs4031.c index 44e3de930ba..ad21ccd14cc 100644 --- a/src/mess/machine/cs4031.c +++ b/src/mess/machine/cs4031.c @@ -170,7 +170,9 @@ static MACHINE_CONFIG_FRAGMENT( cs4031 ) MCFG_PIC8259_ADD("intc1", WRITELINE(cs4031_device, intc1_int_w), VCC, READ8(cs4031_device, intc1_slave_ack_r)) MCFG_PIC8259_ADD("intc2", DEVWRITELINE("intc1", pic8259_device, ir2_w), GND, NULL) MCFG_PIT8254_ADD("ctc", cs4031_pit_config) - MCFG_MC146818_IRQ_ADD("rtc", MC146818_STANDARD, WRITELINE(cs4031_device, rtc_irq_w)) + MCFG_MC146818_ADD("rtc", XTAL_32_768kHz) + MCFG_MC146818_IRQ_HANDLER(WRITELINE(cs4031_device, rtc_irq_w)) + MCFG_MC146818_CENTURY_INDEX(0x32) MACHINE_CONFIG_END machine_config_constructor cs4031_device::device_mconfig_additions() const @@ -317,8 +319,7 @@ void cs4031_device::device_start() m_space_io->install_readwrite_handler(0x0060, 0x0063, read8_delegate(FUNC(cs4031_device::keyb_data_r), this), write8_delegate(FUNC(cs4031_device::keyb_data_w), this), 0x000000ff); m_space_io->install_readwrite_handler(0x0060, 0x0063, read8_delegate(FUNC(cs4031_device::portb_r), this), write8_delegate(FUNC(cs4031_device::portb_w), this), 0x0000ff00); m_space_io->install_readwrite_handler(0x0064, 0x0067, read8_delegate(FUNC(cs4031_device::keyb_status_r), this), write8_delegate(FUNC(cs4031_device::keyb_command_w), this), 0x000000ff); - m_space_io->install_write_handler(0x0070, 0x0073, write8_delegate(FUNC(cs4031_device::rtc_w), this), 0x000000ff); - m_space_io->install_readwrite_handler(0x0070, 0x0073, read8_delegate(FUNC(mc146818_device::data_r), &(*m_rtc)), write8_delegate(FUNC(mc146818_device::data_w), &(*m_rtc)), 0x0000ff00); + m_space_io->install_readwrite_handler(0x0070, 0x0073, read8_delegate(FUNC(mc146818_device::read), &(*m_rtc)), write8_delegate(FUNC(cs4031_device::rtc_w), this), 0x0000ffff); m_space_io->install_readwrite_handler(0x0080, 0x008f, read8_delegate(FUNC(cs4031_device::dma_page_r), this), write8_delegate(FUNC(cs4031_device::dma_page_w), this), 0xffffffff); m_space_io->install_readwrite_handler(0x0090, 0x0093, read8_delegate(FUNC(cs4031_device::sysctrl_r), this), write8_delegate(FUNC(cs4031_device::sysctrl_w), this), 0x00ff0000); m_space_io->install_readwrite_handler(0x00a0, 0x00a3, read8_delegate(FUNC(pic8259_device::read), &(*m_intc2)), write8_delegate(FUNC(pic8259_device::write), &(*m_intc2)), 0x0000ffff); @@ -993,6 +994,11 @@ WRITE8_MEMBER( cs4031_device::rtc_w ) if (0) logerror("cs4031_device::rtc_w: %02x\n", data); - m_nmi_mask = !BIT(data, 7); - m_rtc->address_w(space, 0, data & 0x7f); + if (offset == 0) + { + m_nmi_mask = !BIT(data, 7); + data &= 0x7f; + } + + m_rtc->write(space, offset, data); } diff --git a/src/mess/machine/southbridge.c b/src/mess/machine/southbridge.c index f657edd3afd..98b21cafd29 100644 --- a/src/mess/machine/southbridge.c +++ b/src/mess/machine/southbridge.c @@ -114,7 +114,9 @@ static MACHINE_CONFIG_FRAGMENT( southbridge ) MCFG_PC_KBDC_ADD("pc_kbdc", pc_kbdc_intf) MCFG_PC_KBDC_SLOT_ADD("pc_kbdc", "kbd", pc_at_keyboards, STR_KBD_MICROSOFT_NATURAL) - MCFG_MC146818_IRQ_ADD("rtc", MC146818_STANDARD, DEVWRITELINE("pic8259_slave", pic8259_device, ir0_w)) + MCFG_MC146818_ADD("rtc", XTAL_32_768kHz) + MCFG_MC146818_IRQ_HANDLER(DEVWRITELINE("pic8259_slave", pic8259_device, ir0_w)) + MCFG_MC146818_CENTURY_INDEX(0x32) MCFG_BUS_MASTER_IDE_CONTROLLER_ADD("ide", ata_devices, "hdd", NULL, false) MCFG_ATA_INTERFACE_IRQ_HANDLER(DEVWRITELINE("pic8259_slave", pic8259_device, ir6_w))