From aa8e169f48c85633f7df7bf9d0908e9f436eddc6 Mon Sep 17 00:00:00 2001 From: Ted Green Date: Fri, 23 Jun 2017 13:45:24 -0600 Subject: M48T37 timekeeper: Add watchdog function. (nw) --- src/devices/machine/timekpr.cpp | 61 +++++++++++++++++++++++++++++++++++++++-- src/devices/machine/timekpr.h | 16 +++++++++++ 2 files changed, 75 insertions(+), 2 deletions(-) diff --git a/src/devices/machine/timekpr.cpp b/src/devices/machine/timekpr.cpp index 4269b3379ea..11278d095f5 100644 --- a/src/devices/machine/timekpr.cpp +++ b/src/devices/machine/timekpr.cpp @@ -56,7 +56,7 @@ DEFINE_DEVICE_TYPE(MK48T12, mk48t12_device, "mk48t12", "MK48T12 Timekeeper") #define FLAGS_BL ( 0x10 ) /* MK48T08/M48T37: not emulated */ #define FLAGS_AF ( 0x40 ) /* M48T37: not emulated */ -#define FLAGS_WDF ( 0x80 ) /* M48T37: not emulated */ +#define FLAGS_WDF ( 0x80 ) /* M48T37 */ /*************************************************************************** @@ -91,6 +91,8 @@ static int counter_from_ram( uint8_t *data, int offset ) timekeeper_device::timekeeper_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock, int size) : device_t(mconfig, type, tag, owner, clock) , device_nvram_interface(mconfig, *this) + , m_reset_cb(*this) + , m_irq_cb(*this) , m_default_data(*this, DEVICE_SELF, size) , m_size(size) { @@ -99,6 +101,7 @@ timekeeper_device::timekeeper_device(const machine_config &mconfig, device_type m48t02_device::m48t02_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) : timekeeper_device(mconfig, M48T02, tag, owner, clock, 0x800) { + m_offset_watchdog = -1; m_offset_control = 0x7f8; m_offset_seconds = 0x7f9; m_offset_minutes = 0x7fa; @@ -114,6 +117,7 @@ m48t02_device::m48t02_device(const machine_config &mconfig, const char *tag, dev m48t35_device::m48t35_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) : timekeeper_device(mconfig, M48T35, tag, owner, clock, 0x8000) { + m_offset_watchdog = -1; m_offset_control = 0x7ff8; m_offset_seconds = 0x7ff9; m_offset_minutes = 0x7ffa; @@ -129,6 +133,7 @@ m48t35_device::m48t35_device(const machine_config &mconfig, const char *tag, dev m48t37_device::m48t37_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) : timekeeper_device(mconfig, M48T37, tag, owner, clock, 0x8000) { + m_offset_watchdog = 0x7ff7; m_offset_control = 0x7ff8; m_offset_seconds = 0x7ff9; m_offset_minutes = 0x7ffa; @@ -144,6 +149,7 @@ m48t37_device::m48t37_device(const machine_config &mconfig, const char *tag, dev m48t58_device::m48t58_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) : timekeeper_device(mconfig, M48T58, tag, owner, clock, 0x2000) { + m_offset_watchdog = -1; m_offset_control = 0x1ff8; m_offset_seconds = 0x1ff9; m_offset_minutes = 0x1ffa; @@ -159,6 +165,7 @@ m48t58_device::m48t58_device(const machine_config &mconfig, const char *tag, dev mk48t08_device::mk48t08_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) : timekeeper_device(mconfig, MK48T08, tag, owner, clock, 0x2000) { + m_offset_watchdog = 0x1ff7; m_offset_control = 0x1ff8; m_offset_seconds = 0x1ff9; m_offset_minutes = 0x1ffa; @@ -174,6 +181,7 @@ mk48t08_device::mk48t08_device(const machine_config &mconfig, const char *tag, d mk48t12_device::mk48t12_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) : timekeeper_device(mconfig, MK48T12, tag, owner, clock, 0x2000) { + m_offset_watchdog = -1; m_offset_control = 0x7f8; m_offset_seconds = 0x7f9; m_offset_minutes = 0x7fa; @@ -220,9 +228,16 @@ void timekeeper_device::device_start() save_item( NAME(m_year) ); save_item( NAME(m_century) ); save_item( NAME(m_data) ); + save_item( NAME(m_watchdog_delay)); emu_timer *timer = timer_alloc(); timer->adjust(attotime::from_seconds(1), 0, attotime::from_seconds(1)); + + m_watchdog_timer = machine().scheduler().timer_alloc(timer_expired_delegate(FUNC(timekeeper_device::watchdog_callback), this)); + m_watchdog_timer->adjust(attotime::never); + m_reset_cb.resolve_safe(); + m_irq_cb.resolve_safe(); + } //------------------------------------------------- @@ -328,6 +343,29 @@ void timekeeper_device::device_timer(emu_timer &timer, device_timer_id id, int p } } +TIMER_CALLBACK_MEMBER(timekeeper_device::watchdog_callback) +{ + // Set Flag + m_data[m_offset_flags] |= FLAGS_WDF; + // WDS (bit 7) selects callback + if (m_data[m_offset_watchdog] & 0x80) { + // Clear watchdog register + m_data[m_offset_watchdog] = 0; + m_reset_cb(ASSERT_LINE); + } + else { + m_irq_cb(ASSERT_LINE); + } + //printf("watchdog_callback: WD Control: %02x WD Flags: %02x\n", m_data[m_offset_watchdog], m_data[m_offset_flags]); +} + +WRITE8_MEMBER(timekeeper_device::watchdog_write) +{ + if ((m_data[m_offset_watchdog] & 0x7f) != 0) { + m_watchdog_timer->adjust(m_watchdog_delay); + } +} + WRITE8_MEMBER( timekeeper_device::write ) { if( offset == m_offset_control ) @@ -347,6 +385,21 @@ WRITE8_MEMBER( timekeeper_device::write ) m_day = ( m_day & ~DAY_CEB ) | ( data & DAY_CEB ); } } + else if (offset == m_offset_watchdog) + { + if ((data & 0x7f) == 0) { + m_watchdog_timer->adjust(attotime::never); + } + else { + // Calculate the time unit + m_watchdog_delay = attotime::from_usec(62500); + m_watchdog_delay *= 4 << (data & 0x3); + // Adjust by multiplier + m_watchdog_delay *= (data >> 2) & 0x1f; + m_watchdog_timer->adjust(m_watchdog_delay); + //printf("write: setting watchdog to %s WatchdogReg = 0x%02x\n", m_watchdog_delay.as_string(), data); + } + } m_data[ offset ] = data; } @@ -360,7 +413,11 @@ READ8_MEMBER( timekeeper_device::read ) } else if( offset == m_offset_flags && (type() == MK48T08 || type() == M48T37) ) { - result = 0; + // Clear the watchdog flag + m_data[m_offset_flags] &= ~FLAGS_WDF; + // Clear callbacks + m_reset_cb(CLEAR_LINE); + m_irq_cb(CLEAR_LINE); } return result; } diff --git a/src/devices/machine/timekpr.h b/src/devices/machine/timekpr.h index 63e2e3374ce..3a7983dc291 100644 --- a/src/devices/machine/timekpr.h +++ b/src/devices/machine/timekpr.h @@ -35,6 +35,12 @@ #define MCFG_M48T37_ADD(_tag) \ MCFG_DEVICE_ADD(_tag, M48T37, 0) +#define MCFG_M48T37_RESET_HANDLER(_devcb) \ + devcb = &timekeeper_device::set_reset_handler(*device, DEVCB_##_devcb); + +#define MCFG_M48T37_IRQ_HANDLER(_devcb) \ + devcb = &timekeeper_device::set_irq_handler(*device, DEVCB_##_devcb); + #define MCFG_M48T58_ADD(_tag) \ MCFG_DEVICE_ADD(_tag, M48T58, 0) @@ -58,6 +64,9 @@ class timekeeper_device : public device_t, public device_nvram_interface public: DECLARE_WRITE8_MEMBER( write ); DECLARE_READ8_MEMBER( read ); + DECLARE_WRITE8_MEMBER(watchdog_write); + template static devcb_base &set_reset_handler(device_t &device, Object &&cb) { return downcast(device).m_reset_cb.set_callback(std::forward(cb)); } + template static devcb_base &set_irq_handler(device_t &device, Object &&cb) { return downcast(device).m_irq_cb.set_callback(std::forward(cb)); } protected: // construction/destruction @@ -73,6 +82,10 @@ protected: virtual void nvram_read(emu_file &file) override; virtual void nvram_write(emu_file &file) override; + TIMER_CALLBACK_MEMBER(watchdog_callback); + devcb_write_line m_reset_cb; + devcb_write_line m_irq_cb; + private: void counters_to_ram(); void counters_from_ram(); @@ -91,8 +104,11 @@ private: std::vector m_data; optional_region_ptr m_default_data; + emu_timer* m_watchdog_timer; + attotime m_watchdog_delay; protected: int const m_size; + int m_offset_watchdog; int m_offset_control; int m_offset_seconds; int m_offset_minutes; -- cgit v1.2.3