diff options
Diffstat (limited to 'src/devices/machine/rtc65271.cpp')
-rw-r--r-- | src/devices/machine/rtc65271.cpp | 213 |
1 files changed, 126 insertions, 87 deletions
diff --git a/src/devices/machine/rtc65271.cpp b/src/devices/machine/rtc65271.cpp index 9ccc83997bf..adea3cb29d6 100644 --- a/src/devices/machine/rtc65271.cpp +++ b/src/devices/machine/rtc65271.cpp @@ -21,6 +21,9 @@ #include "emu.h" #include "rtc65271.h" +#include <tuple> + + /* Delay between the beginning (UIP asserted) and the end (UIP cleared and update interrupt asserted) of the update cycle */ #define UPDATE_CYCLE_TIME attotime::from_usec(1984) @@ -162,10 +165,18 @@ static uint8_t BCD_to_binary(uint8_t data) void rtc65271_device::nvram_default() { - memset(m_regs,0, sizeof(m_regs)); - memset(m_xram,0, sizeof(m_xram)); - - m_regs[reg_B] |= reg_B_DM; // Firebeat assumes the chip factory defaults to non-BCD mode (or maybe Konami programs it that way?) + if (m_default_data.found()) + { + auto file = util::ram_read(m_default_data, m_default_data.bytes()); + if (file != nullptr) + nvram_read(*file); + } + else + { + memset(m_regs, 0, sizeof(m_regs)); + memset(m_xram, 0, sizeof(m_xram)); + m_regs[reg_B] |= reg_B_DM; // Firebeat assumes the chip factory defaults to non-BCD mode (or maybe Konami programs it that way?) + } } //------------------------------------------------- @@ -173,84 +184,96 @@ void rtc65271_device::nvram_default() // .nv file //------------------------------------------------- -void rtc65271_device::nvram_read(emu_file &file) +bool rtc65271_device::nvram_read(util::read_stream &file) { uint8_t buf; + std::error_condition err; + size_t actual; /* version flag */ - if (file.read(&buf, 1) != 1) - return; + std::tie(err, actual) = util::read(file, &buf, 1); + if (err || (actual != 1)) + return false; if (buf != 0) - return; + return false; /* control registers */ - if (file.read(&buf, 1) != 1) - return; + std::tie(err, actual) = util::read(file, &buf, 1); + if (err || (actual != 1)) + return false; m_regs[reg_A] = buf & (reg_A_DV /*| reg_A_RS*/); - if (file.read(&buf, 1) != 1) - return; + std::tie(err, actual) = util::read(file, &buf, 1); + if (err || (actual != 1)) + return false; m_regs[reg_B] = buf & (reg_B_SET | reg_B_DM | reg_B_24h | reg_B_DSE); /* alarm registers */ - if (file.read(&m_regs[reg_alarm_second], 1) != 1) - return; - if (file.read(&m_regs[reg_alarm_minute], 1) != 1) - return; - if (file.read(&m_regs[reg_alarm_hour], 1) != 1) - return; + std::tie(err, actual) = util::read(file, &m_regs[reg_alarm_second], 1); + if (err || (actual != 1)) + return false; + std::tie(err, actual) = util::read(file, &m_regs[reg_alarm_minute], 1); + if (err || (actual != 1)) + return false; + std::tie(err, actual) = util::read(file, &m_regs[reg_alarm_hour], 1); + if (err || (actual != 1)) + return false; /* user RAM */ - if (file.read(m_regs+14, 50) != 50) - return; + std::tie(err, actual) = util::read(file, m_regs+14, 50); + if (err || (actual != 50)) + return false; /* extended RAM */ - if (file.read(m_xram, 4096) != 4096) - return; + std::tie(err, actual) = util::read(file, m_xram, 4096); + if (err || (actual != 4096)) + return false; m_regs[reg_D] |= reg_D_VRT; /* the data was backed up successfully */ /*m_dirty = false;*/ - { - system_time systime; - - /* get the current date/time from the core */ - machine().current_datetime(systime); + return true; +} - /* set clock registers */ - m_regs[reg_second] = systime.local_time.second; - m_regs[reg_minute] = systime.local_time.minute; - if (m_regs[reg_B] & reg_B_24h) - /* 24-hour mode */ - m_regs[reg_hour] = systime.local_time.hour; - else - { /* 12-hour mode */ - if (systime.local_time.hour >= 12) - { - m_regs[reg_hour] = 0x80; - systime.local_time.hour -= 12; - } - else - { - m_regs[reg_hour] = 0; - } +//------------------------------------------------- +// rtc_clock_updated - update clock with real time +//------------------------------------------------- - // Firebeat indicates non-BCD 12-hour mode has 0-based hour, so 12 AM is 0x00 and 12 PM is 0x80 - m_regs[reg_hour] |= systime.local_time.hour; // ? systime.local_time.hour : 12; +void rtc65271_device::rtc_clock_updated(int year, int month, int day, int day_of_week, int hour, int minute, int second) +{ + /* set clock registers */ + m_regs[reg_second] = second; + m_regs[reg_minute] = minute; + if (m_regs[reg_B] & reg_B_24h) + /* 24-hour mode */ + m_regs[reg_hour] = hour; + else + { /* 12-hour mode */ + if (hour >= 12) + { + m_regs[reg_hour] = 0x80; + hour -= 12; } - m_regs[reg_weekday] = systime.local_time.weekday + 1; - m_regs[reg_monthday] = systime.local_time.mday; - m_regs[reg_month] = systime.local_time.month + 1; - m_regs[reg_year] = systime.local_time.year % 100; - if (! (m_regs[reg_B] & reg_B_DM)) - { /* BCD mode */ - m_regs[reg_second] = binary_to_BCD(m_regs[reg_second]); - m_regs[reg_minute] = binary_to_BCD(m_regs[reg_minute]); - m_regs[reg_hour] = (m_regs[reg_hour] & 0x80) | binary_to_BCD(m_regs[reg_hour] & 0x7f); - /*m_regs[reg_weekday] = binary_to_BCD(m_regs[reg_weekday]);*/ - m_regs[reg_monthday] = binary_to_BCD(m_regs[reg_monthday]); - m_regs[reg_month] = binary_to_BCD(m_regs[reg_month]); - m_regs[reg_year] = binary_to_BCD(m_regs[reg_year]); + else + { + m_regs[reg_hour] = 0; } + + // Firebeat indicates non-BCD 12-hour mode has 0-based hour, so 12 AM is 0x00 and 12 PM is 0x80 + m_regs[reg_hour] |= hour; // ? hour : 12; + } + m_regs[reg_weekday] = day_of_week; + m_regs[reg_monthday] = day; + m_regs[reg_month] = month; + m_regs[reg_year] = year % 100; + if (! (m_regs[reg_B] & reg_B_DM)) + { /* BCD mode */ + m_regs[reg_second] = binary_to_BCD(m_regs[reg_second]); + m_regs[reg_minute] = binary_to_BCD(m_regs[reg_minute]); + m_regs[reg_hour] = (m_regs[reg_hour] & 0x80) | binary_to_BCD(m_regs[reg_hour] & 0x7f); + /*m_regs[reg_weekday] = binary_to_BCD(m_regs[reg_weekday]);*/ + m_regs[reg_monthday] = binary_to_BCD(m_regs[reg_monthday]); + m_regs[reg_month] = binary_to_BCD(m_regs[reg_month]); + m_regs[reg_year] = binary_to_BCD(m_regs[reg_year]); } } @@ -259,39 +282,50 @@ void rtc65271_device::nvram_read(emu_file &file) // .nv file //------------------------------------------------- -void rtc65271_device::nvram_write(emu_file &file) +bool rtc65271_device::nvram_write(util::write_stream &file) { uint8_t buf; - + std::error_condition err; + size_t actual; /* version flag */ buf = 0; - if (file.write(& buf, 1) != 1) - return; + std::tie(err, actual) = util::write(file, &buf, 1); + if (err) + return false; /* control registers */ buf = m_regs[reg_A] & (reg_A_DV | reg_A_RS); - if (file.write(&buf, 1) != 1) - return; + std::tie(err, actual) = util::write(file, &buf, 1); + if (err) + return false; buf = m_regs[reg_B] & (reg_B_SET | reg_B_DM | reg_B_24h | reg_B_DSE); - if (file.write(&buf, 1) != 1) - return; + std::tie(err, actual) = util::write(file, &buf, 1); + if (err) + return false; /* alarm registers */ - if (file.write(&m_regs[reg_alarm_second], 1) != 1) - return; - if (file.write(&m_regs[reg_alarm_minute], 1) != 1) - return; - if (file.write(&m_regs[reg_alarm_hour], 1) != 1) - return; + std::tie(err, actual) = util::write(file, &m_regs[reg_alarm_second], 1); + if (err) + return false; + std::tie(err, actual) = util::write(file, &m_regs[reg_alarm_minute], 1); + if (err) + return false; + std::tie(err, actual) = util::write(file, &m_regs[reg_alarm_hour], 1); + if (err) + return false; /* user RAM */ - if (file.write(m_regs+14, 50) != 50) - return; + std::tie(err, actual) = util::write(file, m_regs+14, 50); + if (err) + return false; /* extended RAM */ - if (file.write(m_xram, 4096) != 4096) - return; + std::tie(err, actual) = util::write(file, m_xram, 4096); + if (err) + return false; + + return true; } /* @@ -392,7 +426,7 @@ void rtc65271_device::write(int xramsel, offs_t offset, uint8_t data) { attotime period = attotime::from_hz(SQW_freq_table[data & reg_A_RS]); attotime half_period = period / 2; - attotime elapsed = m_update_timer->elapsed(); + attotime elapsed = m_begin_update_timer->elapsed(); if (half_period > elapsed) m_SQW_timer->adjust(half_period - elapsed); @@ -451,17 +485,19 @@ void rtc65271_device::field_interrupts() if (m_regs[reg_C] & m_regs[reg_B] & (reg_C_PF | reg_C_AF | reg_C_UF)) { m_regs[reg_C] |= reg_C_IRQF; - if (!m_interrupt_cb.isnull()) - m_interrupt_cb(1); + m_interrupt_cb(1); } else { m_regs[reg_C] &= ~reg_C_IRQF; - if (!m_interrupt_cb.isnull()) - m_interrupt_cb(0); + m_interrupt_cb(0); } } +int rtc65271_device::intrq_r() +{ + return (m_regs[reg_C] & reg_C_IRQF)? ASSERT_LINE : CLEAR_LINE; +} /* Update SQW output state each half-period and assert periodic interrupt each @@ -493,7 +529,7 @@ TIMER_CALLBACK_MEMBER(rtc65271_device::rtc_begin_update_cb) m_regs[reg_A] |= reg_A_UIP; /* schedule end of update cycle */ - machine().scheduler().timer_set(UPDATE_CYCLE_TIME, timer_expired_delegate(FUNC(rtc65271_device::rtc_end_update_cb), this)); + m_end_update_timer->adjust(UPDATE_CYCLE_TIME); } } @@ -655,7 +691,9 @@ DEFINE_DEVICE_TYPE(RTC65271, rtc65271_device, "rtc65271", "Epson RTC-65271 RTC") rtc65271_device::rtc65271_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) : device_t(mconfig, RTC65271, tag, owner, clock) , device_nvram_interface(mconfig, *this) + , device_rtc_interface(mconfig, *this) , m_interrupt_cb(*this) + , m_default_data(*this, DEVICE_SELF) { } @@ -664,10 +702,11 @@ rtc65271_device::rtc65271_device(const machine_config &mconfig, const char *tag, //------------------------------------------------- void rtc65271_device::device_start() { - m_update_timer = machine().scheduler().timer_alloc(timer_expired_delegate(FUNC(rtc65271_device::rtc_begin_update_cb), this)); - m_update_timer->adjust(attotime::from_seconds(1), 0, attotime::from_seconds(1)); - m_SQW_timer = machine().scheduler().timer_alloc(timer_expired_delegate(FUNC(rtc65271_device::rtc_SQW_cb), this)); - m_interrupt_cb.resolve(); + m_begin_update_timer = timer_alloc(FUNC(rtc65271_device::rtc_begin_update_cb), this); + m_begin_update_timer->adjust(attotime::from_seconds(1), 0, attotime::from_seconds(1)); + m_end_update_timer = timer_alloc(FUNC(rtc65271_device::rtc_end_update_cb), this); + m_end_update_timer->adjust(attotime::never); + m_SQW_timer = timer_alloc(FUNC(rtc65271_device::rtc_SQW_cb), this); save_item(NAME(m_regs)); save_item(NAME(m_cur_reg)); |