Updated the 74123 device to no longer be legacy. [Harmony]

This commit is contained in:
Ryan Holtz 2010-08-23 05:42:12 +00:00
parent 3c0ef980fb
commit 86342429fd
2 changed files with 329 additions and 187 deletions

View File

@ -14,228 +14,287 @@
#define LOG (0)
typedef struct _ttl74123_t ttl74123_t;
//**************************************************************************
// DEVICE CONFIGURATION
//**************************************************************************
struct _ttl74123_t
//-------------------------------------------------
// ttl74123_device_config - constructor
//-------------------------------------------------
ttl74123_device_config::ttl74123_device_config(const machine_config &mconfig, const char *tag, const device_config *owner, UINT32 clock)
: device_config(mconfig, static_alloc_device_config, "TTL74123", tag, owner, clock)
{
const ttl74123_config *intf;
UINT8 a; /* pin 1/9 */
UINT8 b; /* pin 2/10 */
UINT8 clear; /* pin 3/11 */
emu_timer *timer;
};
/* ----------------------------------------------------------------------- */
INLINE ttl74123_t *get_safe_token(running_device *device) {
assert( device != NULL );
assert( device->type() == TTL74123 );
return ( ttl74123_t * ) downcast<legacy_device_base *>(device)->token();
}
static attotime compute_duration(ttl74123_t *chip)
//-------------------------------------------------
// static_alloc_device_config - allocate a new
// configuration object
//-------------------------------------------------
device_config *ttl74123_device_config::static_alloc_device_config(const machine_config &mconfig, const char *tag, const device_config *owner, UINT32 clock)
{
double duration;
switch (chip->intf->connection_type)
{
case TTL74123_NOT_GROUNDED_NO_DIODE:
duration = 0.28 * chip->intf->res * chip->intf->cap * (1.0 + (700.0 / chip->intf->res));
break;
case TTL74123_NOT_GROUNDED_DIODE:
duration = 0.25 * chip->intf->res * chip->intf->cap * (1.0 + (700.0 / chip->intf->res));
break;
case TTL74123_GROUNDED:
default:
if (chip->intf->cap < CAP_U(0.1))
/* this is really a curve - a very flat one in the 0.1uF-.01uF range */
duration = 0.32 * chip->intf->res * chip->intf->cap;
else
duration = 0.33 * chip->intf->res * chip->intf->cap;
break;
}
return double_to_attotime(duration);
return global_alloc(ttl74123_device_config(mconfig, tag, owner, clock));
}
static int timer_running(ttl74123_t *chip)
//-------------------------------------------------
// alloc_device - allocate a new device object
//-------------------------------------------------
device_t *ttl74123_device_config::alloc_device(running_machine &machine) const
{
return (attotime_compare(timer_timeleft(chip->timer), attotime_zero) > 0) &&
(attotime_compare(timer_timeleft(chip->timer), attotime_never) != 0);
return auto_alloc(&machine, ttl74123_device(machine, *this));
}
static TIMER_CALLBACK( output_callback )
//-------------------------------------------------
// device_config_complete - perform any
// operations now that the configuration is
// complete
//-------------------------------------------------
void ttl74123_device_config::device_config_complete()
{
running_device *device = (running_device *)ptr;
ttl74123_t *chip = get_safe_token(device);
chip->intf->output_changed_cb(device, 0, param);
}
static void set_output(running_device *device)
{
ttl74123_t *chip = get_safe_token(device);
int output = timer_running(chip);
timer_set( device->machine, attotime_zero, (void *) device, output, output_callback );
if (LOG) logerror("74123 %s: Output: %d\n", device->tag(), output);
}
static TIMER_CALLBACK( clear_callback )
{
running_device *device = (running_device *)ptr;
ttl74123_t *chip = get_safe_token(device);
int output = timer_running(chip);
chip->intf->output_changed_cb(device, 0, output);
}
//**************************************************************************
// LIVE DEVICE
//**************************************************************************
static void start_pulse(running_device *device)
//-------------------------------------------------
// ttl74123_device - constructor
//-------------------------------------------------
ttl74123_device::ttl74123_device(running_machine &_machine, const ttl74123_device_config &config)
: device_t(_machine, config),
m_config(config)
{
ttl74123_t *chip = get_safe_token(device);
attotime duration = compute_duration(chip);
}
if (timer_running(chip))
{
/* retriggering, but not if we are called to quickly */
attotime delay_time = attotime_make(0, ATTOSECONDS_PER_SECOND * chip->intf->cap * 220);
if (attotime_compare(timer_timeelapsed(chip->timer), delay_time) >= 0)
{
timer_adjust_oneshot(chip->timer, duration, 0);
//-------------------------------------------------
// device_start - device-specific startup
//-------------------------------------------------
if (LOG) logerror("74123 %s: Retriggering pulse. Duration: %f\n", device->tag(), attotime_to_double(duration));
}
else
{
if (LOG) logerror("74123 %s: Retriggering failed.\n", device->tag());
}
}
else
{
/* starting */
timer_adjust_oneshot(chip->timer, duration, 0);
void ttl74123_device::device_start()
{
m_timer = timer_alloc(&m_machine, clear_callback, (void *)this);
set_output(device);
/* start with the defaults */
m_a = m_config.m_a;
m_b = m_config.m_b;
m_clear = m_config.m_clear;
if (LOG) logerror("74123 %s: Starting pulse. Duration: %f\n", device->tag(), attotime_to_double(duration));
}
/* register for state saving */
state_save_register_device_item(this, 0, m_a);
state_save_register_device_item(this, 0, m_b);
state_save_register_device_item(this, 0, m_clear);
}
//-------------------------------------------------
// device_reset - device-specific reset
//-------------------------------------------------
void ttl74123_device::device_reset()
{
set_output();
}
/*-------------------------------------------------
compute_duration
-------------------------------------------------*/
attotime ttl74123_device::compute_duration()
{
double duration;
switch (m_config.m_connection_type)
{
case TTL74123_NOT_GROUNDED_NO_DIODE:
duration = 0.28 * m_config.m_res * m_config.m_cap * (1.0 + (700.0 / m_config.m_res));
break;
case TTL74123_NOT_GROUNDED_DIODE:
duration = 0.25 * m_config.m_res * m_config.m_cap * (1.0 + (700.0 / m_config.m_res));
break;
case TTL74123_GROUNDED:
default:
if (m_config.m_cap < CAP_U(0.1))
{
/* this is really a curve - a very flat one in the 0.1uF-.01uF range */
duration = 0.32 * m_config.m_res * m_config.m_cap;
}
else
{
duration = 0.33 * m_config.m_res * m_config.m_cap;
}
break;
}
return double_to_attotime(duration);
}
/*-------------------------------------------------
timer_running
-------------------------------------------------*/
int ttl74123_device::timer_running()
{
return (attotime_compare(timer_timeleft(m_timer), attotime_zero) > 0) &&
(attotime_compare(timer_timeleft(m_timer), attotime_never) != 0);
}
/*-------------------------------------------------
TIMER_CALLBACK( output_callback )
-------------------------------------------------*/
TIMER_CALLBACK( ttl74123_device::output_callback )
{
ttl74123_device *dev = reinterpret_cast<ttl74123_device*>(ptr);
dev->output(param);
}
void ttl74123_device::output(INT32 param)
{
m_config.m_output_changed_cb(this, 0, param);
}
void ttl74123_device::set_output()
{
int output = timer_running();
timer_set( &m_machine, attotime_zero, (void *)this, output, output_callback );
if (LOG) logerror("74123 %s: Output: %d\n", tag(), output);
}
TIMER_CALLBACK( ttl74123_device::clear_callback )
{
ttl74123_device *dev = reinterpret_cast<ttl74123_device*>(ptr);
dev->clear();
}
void ttl74123_device::clear()
{
int output = timer_running();
m_config.m_output_changed_cb(this, 0, output);
}
void ttl74123_device::start_pulse()
{
attotime duration = compute_duration();
if(timer_running())
{
/* retriggering, but not if we are called to quickly */
attotime delay_time = attotime_make(0, ATTOSECONDS_PER_SECOND * m_config.m_cap * 220);
if(attotime_compare(timer_timeelapsed(m_timer), delay_time) >= 0)
{
timer_adjust_oneshot(m_timer, duration, 0);
if (LOG) logerror("74123 %s: Retriggering pulse. Duration: %f\n", tag(), attotime_to_double(duration));
}
else
{
if (LOG) logerror("74123 %s: Retriggering failed.\n", tag());
}
}
else
{
/* starting */
timer_adjust_oneshot(m_timer, duration, 0);
set_output();
if (LOG) logerror("74123 %s: Starting pulse. Duration: %f\n", tag(), attotime_to_double(duration));
}
}
WRITE8_DEVICE_HANDLER( ttl74123_a_w )
{
ttl74123_t *chip = get_safe_token(device);
ttl74123_device *dev = reinterpret_cast<ttl74123_device *>(device);
dev->a_w(data);
}
/* start/regtrigger pulse if B=HI and falling edge on A (while clear is HI) */
if (!data && chip->a && chip->b && chip->clear)
start_pulse(device);
void ttl74123_device::a_w(UINT8 data)
{
/* start/regtrigger pulse if B=HI and falling edge on A (while clear is HI) */
if (!data && m_a && m_b && m_clear)
{
start_pulse();
}
chip->a = data;
m_a = data;
}
WRITE8_DEVICE_HANDLER( ttl74123_b_w )
{
ttl74123_t *chip = get_safe_token(device);
ttl74123_device *dev = reinterpret_cast<ttl74123_device *>(device);
dev->b_w(data);
}
/* start/regtrigger pulse if A=LO and rising edge on B (while clear is HI) */
if (data && !chip->b && !chip->a && chip->clear)
start_pulse(device);
void ttl74123_device::b_w(UINT8 data)
{
/* start/regtrigger pulse if A=LO and rising edge on B (while clear is HI) */
if (data && !m_b && !m_a && m_clear)
{
start_pulse();
}
chip->b = data;
m_b = data;
}
WRITE8_DEVICE_HANDLER( ttl74123_clear_w )
{
ttl74123_t *chip = get_safe_token(device);
ttl74123_device *dev = reinterpret_cast<ttl74123_device *>(device);
dev->clear_w(data);
}
/* start/regtrigger pulse if B=HI and A=LO and rising edge on clear */
if (data && !chip->a && chip->b && !chip->clear)
start_pulse(device);
else if (!data) /* clear the output */
{
timer_adjust_oneshot(chip->timer, attotime_zero, 0);
void ttl74123_device::clear_w(UINT8 data)
{
/* start/regtrigger pulse if B=HI and A=LO and rising edge on clear */
if (data && !m_a && m_b && !m_clear)
{
start_pulse();
}
else if (!data) /* clear the output */
{
timer_adjust_oneshot(m_timer, attotime_zero, 0);
if (LOG) logerror("74123 #%s: Cleared\n", device->tag() );
}
chip->clear = data;
if (LOG) logerror("74123 #%s: Cleared\n", tag() );
}
m_clear = data;
}
WRITE8_DEVICE_HANDLER( ttl74123_reset_w )
{
set_output(device);
ttl74123_device *dev = reinterpret_cast<ttl74123_device *>(device);
dev->reset_w();
}
/* ----------------------------------------------------------------------- */
/* device interface */
static DEVICE_START( ttl74123 )
void ttl74123_device::reset_w()
{
ttl74123_t *chip = get_safe_token(device);
/* validate arguments */
chip->intf = (ttl74123_config *)device->baseconfig().static_config();
assert_always(chip->intf, "No interface specified");
assert_always((chip->intf->connection_type != TTL74123_GROUNDED) || (chip->intf->cap >= CAP_U(0.01)), "Only capacitors >= 0.01uF supported for GROUNDED type");
assert_always(chip->intf->cap >= CAP_P(1000), "Only capacitors >= 1000pF supported ");
chip->timer = timer_alloc(device->machine, clear_callback, (void *) device);
/* start with the defaults */
chip->a = chip->intf->a;
chip->b = chip->intf->b;
chip->clear = chip->intf->clear;
/* register for state saving */
state_save_register_device_item(device, 0, chip->a);
state_save_register_device_item(device, 0, chip->b);
state_save_register_device_item(device, 0, chip->clear);
set_output();
}
static DEVICE_RESET( ttl74123 )
{
set_output(device);
}
DEVICE_GET_INFO( ttl74123 )
{
switch (state)
{
/* --- the following bits of info are returned as 64-bit signed integers --- */
case DEVINFO_INT_TOKEN_BYTES: info->i = sizeof(ttl74123_t); break;
case DEVINFO_INT_INLINE_CONFIG_BYTES: info->i = 0; break;
/* --- the following bits of info are returned as pointers to data or functions --- */
case DEVINFO_FCT_START: info->start = DEVICE_START_NAME(ttl74123); break;
case DEVINFO_FCT_STOP: /* Nothing */ break;
case DEVINFO_FCT_RESET: info->reset = DEVICE_RESET_NAME(ttl74123); break;
/* --- the following bits of info are returned as NULL-terminated strings --- */
case DEVINFO_STR_NAME: strcpy(info->s, "74123"); break;
case DEVINFO_STR_FAMILY: strcpy(info->s, "TTL"); break;
case DEVINFO_STR_VERSION: strcpy(info->s, "1.0"); break;
case DEVINFO_STR_SOURCE_FILE: strcpy(info->s, __FILE__); break;
case DEVINFO_STR_CREDITS: strcpy(info->s, "Copyright Nicola Salmoria and the MAME Team"); break;
}
}
DEFINE_LEGACY_DEVICE(TTL74123, ttl74123);
const device_type TTL74123 = ttl74123_device_config::static_alloc_device_config;

View File

@ -43,18 +43,23 @@
*****************************************************************************/
#ifndef TTL74123_H
#define TTL74123_H
#pragma once
#include "devlegcy.h"
#ifndef __TTL74123_H__
#define __TTL74123_H__
DECLARE_LEGACY_DEVICE(TTL74123, ttl74123);
#include "emu.h"
/***************************************************************************
DEVICE CONFIGURATION MACROS
***************************************************************************/
#define MDRV_TTL74123_ADD(_tag, _config) \
MDRV_DEVICE_ADD(_tag, TTL74123, 0) \
MDRV_DEVICE_CONFIG(_config)
/* constants for the different ways the cap/res can be connected.
This determines the formula for calculating the pulse width */
#define TTL74123_NOT_GROUNDED_NO_DIODE (1)
@ -62,26 +67,104 @@ DECLARE_LEGACY_DEVICE(TTL74123, ttl74123);
#define TTL74123_GROUNDED (3)
typedef struct _ttl74123_config ttl74123_config;
struct _ttl74123_config
/***************************************************************************
TYPE DEFINITIONS
***************************************************************************/
// ======================> ttl74123_interface
struct ttl74123_interface
{
int connection_type; /* the hook up type - one of the constants above */
double res; /* resistor connected to RCext */
double cap; /* capacitor connected to Cext and RCext */
int a; /* initial/constant value of the A pin */
int b; /* initial/constant value of the B pin */
int clear; /* initial/constant value of the Clear pin */
write8_device_func output_changed_cb;
int m_connection_type; /* the hook up type - one of the constants above */
double m_res; /* resistor connected to RCext */
double m_cap; /* capacitor connected to Cext and RCext */
int m_a; /* initial/constant value of the A pin */
int m_b; /* initial/constant value of the B pin */
int m_clear; /* initial/constant value of the Clear pin */
write8_device_func m_output_changed_cb;
};
/* write inputs */
// ======================> ttl74123_device_config
class ttl74123_device_config : public device_config,
public ttl74123_interface
{
friend class ttl74123_device;
// construction/destruction
ttl74123_device_config(const machine_config &mconfig, const char *tag, const device_config *owner, UINT32 clock);
public:
// allocators
static device_config *static_alloc_device_config(const machine_config &mconfig, const char *tag, const device_config *owner, UINT32 clock);
virtual device_t *alloc_device(running_machine &machine) const;
protected:
// device_config overrides
virtual void device_config_complete();
};
// ======================> ttl74123_device
class ttl74123_device : public device_t
{
friend class ttl74123_device_config;
// construction/destruction
ttl74123_device(running_machine &_machine, const ttl74123_device_config &_config);
public:
void a_w(UINT8 data);
void b_w(UINT8 data);
void clear_w(UINT8 data);
void reset_w();
protected:
// device-level overrides
virtual void device_start();
virtual void device_reset();
virtual void device_post_load() { }
virtual void device_clock_changed() { }
static TIMER_CALLBACK( output_callback );
static TIMER_CALLBACK( clear_callback );
private:
int timer_running();
void start_pulse();
void output(INT32 param);
void set_output();
attotime compute_duration();
void clear();
UINT8 m_a; /* pin 1/9 */
UINT8 m_b; /* pin 2/10 */
UINT8 m_clear; /* pin 3/11 */
emu_timer *m_timer;
const ttl74123_device_config &m_config;
};
// device type definition
extern const device_type TTL74123;
/***************************************************************************
PROTOTYPES
***************************************************************************/
WRITE8_DEVICE_HANDLER( ttl74123_a_w );
WRITE8_DEVICE_HANDLER( ttl74123_b_w );
WRITE8_DEVICE_HANDLER( ttl74123_clear_w );
/* reset the latch */
WRITE8_DEVICE_HANDLER( ttl74123_reset_w );
WRITE8_DEVICE_HANDLER( ttl74123_reset_w ); /* reset the latch */
#endif