|
|
// license:BSD-3-Clause
// copyright-holders:Aaron Giles
/***************************************************************************
watchdog.c
Watchdog timer device.
***************************************************************************/
#include "emu.h"
#include "watchdog.h"
#include "emuopts.h"
#include "screen.h"
//**************************************************************************
// WATCHDOG TIMER DEVICE
//**************************************************************************
DEFINE_DEVICE_TYPE(WATCHDOG_TIMER, watchdog_timer_device, "watchdog", "Watchdog Timer")
//-------------------------------------------------
// watchdog_timer_device - constructor
//-------------------------------------------------
watchdog_timer_device::watchdog_timer_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
: device_t(mconfig, WATCHDOG_TIMER, tag, owner, clock)
, m_vblank_count(0)
, m_time(attotime::zero)
, m_screen_tag(nullptr)
{
}
//-------------------------------------------------
// device_validity_check - validate the device
// configuration
//-------------------------------------------------
void watchdog_timer_device::device_validity_check(validity_checker &valid) const
{
if (m_vblank_count != 0)
{
screen_device *screen = dynamic_cast<screen_device *>(siblingdevice(m_screen_tag));
if (screen == nullptr)
osd_printf_error("Invalid screen tag specified\n");
}
}
//-------------------------------------------------
// device_start - perform device-specific
// startup
//-------------------------------------------------
void watchdog_timer_device::device_start()
{
// initialize the watchdog
m_counter = 0;
m_timer = timer_alloc();
if (m_vblank_count != 0)
{
// fetch the screen
screen_device *screen = siblingdevice<screen_device>(m_screen_tag);
if (screen != nullptr)
screen->register_vblank_callback(vblank_state_delegate(&watchdog_timer_device::watchdog_vblank, this));
}
save_item(NAME(m_enabled));
save_item(NAME(m_counter));
}
//-------------------------------------------------
// device_reset - reset the device
//-------------------------------------------------
void watchdog_timer_device::device_reset()
{
// set up the watchdog timer; only start off enabled if explicitly configured
m_enabled = (m_vblank_count != 0 || m_time != attotime::zero);
watchdog_reset();
m_enabled = true;
}
//-------------------------------------------------
// device_timer - handle timer expiration events
//-------------------------------------------------
void watchdog_timer_device::device_timer(emu_timer &timer, device_timer_id id, int param, void *ptr)
{
watchdog_fired();
}
//-------------------------------------------------
// watchdog_reset - reset the watchdog timer
//-------------------------------------------------
void watchdog_timer_device::watchdog_reset()
{
// if we're not enabled, skip it
if (!m_enabled)
m_timer->adjust(attotime::never);
// VBLANK-based watchdog?
else if (m_vblank_count != 0)
m_counter = m_vblank_count;
// timer-based watchdog?
else if (m_time != attotime::zero)
m_timer->adjust(m_time);
// default to an obscene amount of time (3 seconds)
else
m_timer->adjust(attotime::from_seconds(3));
}
//-------------------------------------------------
// watchdog_enable - reset the watchdog timer
//-------------------------------------------------
void watchdog_timer_device::watchdog_enable(bool enable)
{
// when re-enabled, we reset our state
if (m_enabled != enable)
{
m_enabled = enable;
watchdog_reset();
}
}
//-------------------------------------------------
// watchdog_fired - trigger machine reset
//-------------------------------------------------
void watchdog_timer_device::watchdog_fired()
{
logerror("Reset caused by the watchdog!!!\n");
bool verbose = machine().options().verbose();
#ifdef MAME_DEBUG
verbose = true;
#endif
if (verbose)
popmessage("Reset caused by the watchdog!!!\n");
machine().schedule_soft_reset();
}
//-------------------------------------------------
// watchdog_vblank - VBLANK state callback for
// watchdog timers
//-------------------------------------------------
void watchdog_timer_device::watchdog_vblank(screen_device &screen, bool vblank_state)
{
// VBLANK starting
if (vblank_state && m_enabled)
{
// check the watchdog
if (m_vblank_count != 0)
if (--m_counter == 0)
watchdog_fired();
}
}
//**************************************************************************
// WATCHDOG READ/WRITE HELPERS
//**************************************************************************
//-------------------------------------------------
// 8-bit reset read/write handlers
//-------------------------------------------------
WRITE8_MEMBER( watchdog_timer_device::reset_w ) { watchdog_reset(); }
READ8_MEMBER( watchdog_timer_device::reset_r ) { watchdog_reset(); return space.unmap(); }
//-------------------------------------------------
// 16-bit reset read/write handlers
//-------------------------------------------------
WRITE16_MEMBER( watchdog_timer_device::reset16_w ) { watchdog_reset(); }
READ16_MEMBER( watchdog_timer_device::reset16_r ) { watchdog_reset(); return space.unmap(); }
//-------------------------------------------------
// 32-bit reset read/write handlers
//-------------------------------------------------
WRITE32_MEMBER( watchdog_timer_device::reset32_w ) { watchdog_reset(); }
READ32_MEMBER( watchdog_timer_device::reset32_r ) { watchdog_reset(); return space.unmap(); }
|