From 627b2d6192857d69fb540260f75ecdca42179373 Mon Sep 17 00:00:00 2001 From: Michael Zapf Date: Sat, 20 Jun 2020 23:22:59 +0200 Subject: bq48x2: Derive clock chip from device_rtc_interface. --- src/devices/machine/bq4847.cpp | 1 - src/devices/machine/bq48x2.cpp | 117 ++++++++++++++++++++++------------------- src/devices/machine/bq48x2.h | 21 +++++--- 3 files changed, 76 insertions(+), 63 deletions(-) diff --git a/src/devices/machine/bq4847.cpp b/src/devices/machine/bq4847.cpp index 3c0ec0c1e94..09afd9b9424 100644 --- a/src/devices/machine/bq4847.cpp +++ b/src/devices/machine/bq4847.cpp @@ -535,7 +535,6 @@ void bq4847_device::nvram_default() void bq4847_device::nvram_read(emu_file &file) { file.read(m_reg, 16); - // get_system_time(); transfer_to_access(); // Clear the saved flags diff --git a/src/devices/machine/bq48x2.cpp b/src/devices/machine/bq48x2.cpp index dbfb1240357..40bfde5a754 100644 --- a/src/devices/machine/bq48x2.cpp +++ b/src/devices/machine/bq48x2.cpp @@ -17,9 +17,6 @@ #define VERBOSE ( LOG_GENERAL | LOG_WARN ) #include "logmacro.h" -// Need to check whether these chips really support leap year handling -#define DOLEAPYEARS 1 - // device type definition DEFINE_DEVICE_TYPE(BQ4842, bq4842_device, "bq4842", "Benchmarq BQ4842 RTC") DEFINE_DEVICE_TYPE(BQ4852, bq4852_device, "bq4852", "Benchmarq BQ4852 RTC") @@ -65,6 +62,7 @@ enum bq48x2_device::bq48x2_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, int memsize) : device_t(mconfig, type, tag, owner, 0), device_nvram_interface(mconfig, *this), + device_rtc_interface(mconfig, *this), m_interrupt_cb(*this), m_resetout_cb(*this), m_memsize(memsize) @@ -87,6 +85,21 @@ bq4852_device::bq4852_device(const machine_config &mconfig, const char *tag, dev { } +/* + Inherited from device_rtc_interface. The date and time is given as integer + and must be converted to BCD. +*/ +void bq48x2_device::rtc_clock_updated(int year, int month, int day, int day_of_week, int hour, int minute, int second) +{ + m_intreg[reg_hours] = convert_to_bcd(hour); + m_intreg[reg_minutes] = convert_to_bcd(minute); + m_intreg[reg_seconds] = convert_to_bcd(second); + m_intreg[reg_year] = convert_to_bcd(year); + m_intreg[reg_month] = convert_to_bcd(month); + m_intreg[reg_date] = convert_to_bcd(day); + m_intreg[reg_days] = convert_to_bcd(day_of_week); +} + bool bq48x2_device::increment_bcd(uint8_t& bcdnumber, uint8_t limit, uint8_t min) { if (!valid_bcd(bcdnumber, min, limit)) @@ -114,6 +127,7 @@ bool bq48x2_device::increment_bcd(uint8_t& bcdnumber, uint8_t limit, uint8_t min return false; } +// TODO: Remove; the real clock cannot verify BCD numbers. bool bq48x2_device::valid_bcd(uint8_t value, uint8_t min, uint8_t max) { bool valid = ((value>=min) && (value<=max) && ((value&0x0f)<=9)); @@ -121,11 +135,6 @@ bool bq48x2_device::valid_bcd(uint8_t value, uint8_t min, uint8_t max) return valid; } -uint8_t bq48x2_device::to_bcd(uint8_t value) -{ - return (((value / 10) << 4) & 0xf0) | (value % 10); -} - // ---------------------------------------------------- /* @@ -134,13 +143,6 @@ uint8_t bq48x2_device::to_bcd(uint8_t value) */ TIMER_CALLBACK_MEMBER(bq48x2_device::rtc_clock_cb) { - // BCD-encoded numbers - static const int days_in_month_table[12] = - { - 0x31,0x28,0x31, 0x30,0x31,0x30, - 0x31, 0x31, 0x30, 0x31, 0x30, 0x31 - }; - // Just for debugging static const char* dow[7] = { "Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat" }; @@ -152,6 +154,7 @@ TIMER_CALLBACK_MEMBER(bq48x2_device::rtc_clock_cb) return; // When the timer ticks, the 100ths are 0. + // TODO: Verify this with a real chip m_intreg[reg_100ths] = 0; if (carry) @@ -162,33 +165,19 @@ TIMER_CALLBACK_MEMBER(bq48x2_device::rtc_clock_cb) if (carry) carry = increment_bcd(m_intreg[reg_minutes], 0x59, 0); - if (carry) - carry = increment_bcd(m_intreg[reg_hours], 0x23, 0); - if (carry) { - uint8_t month = m_intreg[reg_month]; - uint8_t days = 30; - - if (valid_bcd(month, 0x01, 0x12)) - days = days_in_month_table[month-1]; - - // Are leap years considered? - #if DOLEAPYEARS - if ((month==2) - && ((m_intreg[reg_year]%4)==0) - && ((m_intreg[reg_year]%100)!=0 - || (m_intreg[reg_year]%400)==0)) - days = 0x29; - #endif - - increment_bcd(m_intreg[reg_days], 7, 1); // increment the day-of-week (no carry) - carry = increment_bcd(m_intreg[reg_date], days, 1); // and now the day + increment_bcd(m_intreg[reg_hours], 0xff, 0); + if (m_intreg[reg_hours] == 0x24) + { + m_intreg[reg_hours] = 0; + carry = true; + } } if (carry) - carry = increment_bcd(m_intreg[reg_month], 0x12, 1); - if (carry) - carry = increment_bcd(m_intreg[reg_year], 0x99, 0); + { + advance_days_bcd(); + } LOGMASKED(LOG_CLOCK, "%s 20%02x-%02x-%02x %02x:%02x:%02x\n", dow[m_intreg[reg_days]-1], m_intreg[reg_year], m_intreg[reg_month], m_intreg[reg_date], @@ -213,6 +202,40 @@ TIMER_CALLBACK_MEMBER(bq48x2_device::rtc_clock_cb) } } } +void bq48x2_device::advance_days_bcd() +{ + bool carry = false; + + // BCD-encoded numbers + static const int days_in_month_table[12] = + { + 0x31, 0x28, 0x31, 0x30, 0x31, 0x30, + 0x31, 0x31, 0x30, 0x31, 0x30, 0x31 + }; + + uint8_t month = bcd_to_integer(m_intreg[reg_month]); + if (month > 12) month = 12; + + // if (!valid_bcd(month, 0x01, 0x12)) month = 1; + uint8_t days = days_in_month_table[month-1]; + + // Leap years are indeed handled (but the year is only 2-digit) + if ((month==2) && ((m_intreg[reg_year]%4)==0)) + days = 0x29; + + increment_bcd(m_intreg[reg_days], 7, 1); // Increment the day-of-week (without carry) + carry = increment_bcd(m_intreg[reg_date], days, 1); + + if (carry) + { + increment_bcd(m_intreg[reg_month], 0xff, 1); + if (m_intreg[reg_month] == 0x13) + { + m_intreg[reg_month] = 0x01; + increment_bcd(m_intreg[reg_year], 0xff, 0); + } + } +} uint8_t bq48x2_device::get_register(int number, uint8_t mask) { @@ -251,6 +274,7 @@ void bq48x2_device::transfer_to_int() m_intreg[i] = get_register(i, regmask[i]); // If we set the 100ths not to be 0, the next second will occur earlier + // TODO: Check this with the real chip if (hds != m_intreg[reg_100ths]) m_clock_timer->adjust(attotime::from_msec(get_delay()), 0, attotime::from_seconds(1)); } @@ -475,21 +499,6 @@ void bq48x2_device::connect_osc(bool conn) } } -void bq48x2_device::get_system_time() -{ - // Set time from system time - system_time systime; - machine().current_datetime(systime); - m_intreg[reg_hours] = to_bcd(systime.local_time.hour); - m_intreg[reg_minutes] = to_bcd(systime.local_time.minute); - m_intreg[reg_seconds] = to_bcd(systime.local_time.second); - m_intreg[reg_year] = to_bcd(systime.local_time.year%100); - m_intreg[reg_month] = to_bcd(systime.local_time.month+1); - m_intreg[reg_date] = to_bcd(systime.local_time.mday); - m_intreg[reg_days] = to_bcd(systime.local_time.weekday+1); - m_intreg[reg_100ths] = 0; -} - int bq48x2_device::get_delay() { int hds = ((m_intreg[reg_100ths] & 0xf0)>>16) * 10 + (m_intreg[reg_100ths] & 0x0f); @@ -522,7 +531,6 @@ void bq48x2_device::device_start() save_pointer(NAME(m_intreg), 8); // Start clock - get_system_time(); connect_osc(true); } @@ -537,7 +545,6 @@ void bq48x2_device::nvram_read(emu_file &file) { file.read(m_sram.get(), m_memsize); - get_system_time(); transfer_to_access(); // Transfer the system time into the readable registers // Clear the saved flags diff --git a/src/devices/machine/bq48x2.h b/src/devices/machine/bq48x2.h index 359cca282b6..ddf4505b44f 100644 --- a/src/devices/machine/bq48x2.h +++ b/src/devices/machine/bq48x2.h @@ -13,9 +13,13 @@ #pragma once +#include "dirtc.h" + // ======================> bq48x2_device -class bq48x2_device : public device_t, public device_nvram_interface +class bq48x2_device : public device_t, + public device_nvram_interface, + public device_rtc_interface { public: auto interrupt_cb() { return m_interrupt_cb.bind(); } @@ -60,12 +64,15 @@ protected: void set_watchdog_timer(); private: + // Inherited from device_rtc_interface + void rtc_clock_updated(int year, int month, int day, int day_of_week, int hour, int minute, int second) override; + bool rtc_feature_y2k() const override { return false; } + bool rtc_feature_leap_year() const override { return true; } + bool rtc_battery_backed() const override { return true; } + // Sanity-check BCD number bool valid_bcd(uint8_t value, uint8_t min, uint8_t max); - // Convert to BCD - uint8_t to_bcd(uint8_t value); - // Increment BCD number bool increment_bcd(uint8_t& bcdnumber, uint8_t limit, uint8_t min); @@ -84,6 +91,9 @@ private: // Check bits in register bool is_set(int number, uint8_t flag); + // Advance + void advance_days_bcd(); + // Copy register contents from the internal registers to SRAM or back void transfer_to_int(); void transfer_to_access(); @@ -100,9 +110,6 @@ private: // Set timers void set_periodic_timer(); - // Get time from system - void get_system_time(); - // Get the delay until the next second int get_delay(); -- cgit v1.2.3