summaryrefslogtreecommitdiffstatshomepage
path: root/trunk/src/emu/machine/74123.c
diff options
context:
space:
mode:
Diffstat (limited to 'trunk/src/emu/machine/74123.c')
-rw-r--r--trunk/src/emu/machine/74123.c304
1 files changed, 304 insertions, 0 deletions
diff --git a/trunk/src/emu/machine/74123.c b/trunk/src/emu/machine/74123.c
new file mode 100644
index 00000000000..eac124eeae4
--- /dev/null
+++ b/trunk/src/emu/machine/74123.c
@@ -0,0 +1,304 @@
+/*****************************************************************************
+
+ 74123 monoflop emulator - see 74123.h for pin out and truth table
+
+ Formulas came from the TI datasheet revised on March 1998
+
+ *****************************************************************************/
+
+#include "emu.h"
+#include "machine/74123.h"
+#include "machine/rescap.h"
+
+
+#define LOG (0)
+
+
+
+//**************************************************************************
+// LIVE DEVICE
+//**************************************************************************
+
+// device type definition
+const device_type TTL74123 = &device_creator<ttl74123_device>;
+
+//-------------------------------------------------
+// ttl74123_device - constructor
+//-------------------------------------------------
+
+ttl74123_device::ttl74123_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock)
+ : device_t(mconfig, TTL74123, "TTL74123", tag, owner, clock)
+{
+
+}
+
+
+//-------------------------------------------------
+// device_config_complete - perform any
+// operations now that the configuration is
+// complete
+//-------------------------------------------------
+
+void ttl74123_device::device_config_complete()
+{
+ // inherit a copy of the static data
+ const ttl74123_interface *intf = reinterpret_cast<const ttl74123_interface *>(static_config());
+ if (intf != NULL)
+ *static_cast<ttl74123_interface *>(this) = *intf;
+
+ // or initialize to defaults if none provided
+ else
+ {
+ m_connection_type = TTL74123_NOT_GROUNDED_NO_DIODE;
+ m_res = 1.0;
+ m_cap = 1.0;
+ m_a = 0;
+ m_b = 0;
+ m_clear = 0;
+ memset(&m_output_changed_cb, 0, sizeof(m_output_changed_cb));
+ }
+}
+
+
+//-------------------------------------------------
+// device_start - device-specific startup
+//-------------------------------------------------
+
+void ttl74123_device::device_start()
+{
+ m_timer = machine().scheduler().timer_alloc(FUNC(clear_callback), (void *)this);
+
+ /* register for state saving */
+ save_item(NAME(m_a));
+ save_item(NAME(m_b));
+ save_item(NAME(m_clear));
+}
+
+
+//-------------------------------------------------
+// device_reset - device-specific reset
+//-------------------------------------------------
+
+void ttl74123_device::device_reset()
+{
+ set_output();
+}
+
+
+
+//-------------------------------------------------
+// compute_duration - compute timer duration
+//-------------------------------------------------
+
+attotime ttl74123_device::compute_duration()
+{
+ double duration;
+
+ switch (m_connection_type)
+ {
+ case TTL74123_NOT_GROUNDED_NO_DIODE:
+ duration = 0.28 * m_res * m_cap * (1.0 + (700.0 / m_res));
+ break;
+
+ case TTL74123_NOT_GROUNDED_DIODE:
+ duration = 0.25 * m_res * m_cap * (1.0 + (700.0 / m_res));
+ break;
+
+ case TTL74123_GROUNDED:
+ default:
+ if (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_res * m_cap;
+ }
+ else
+ {
+ duration = 0.33 * m_res * m_cap;
+ }
+ break;
+ }
+
+ return attotime::from_double(duration);
+}
+
+
+//-------------------------------------------------
+// timer_running - is the timer running?
+//-------------------------------------------------
+
+int ttl74123_device::timer_running()
+{
+ return (m_timer->remaining() > attotime::zero) &&
+ (m_timer->remaining() != attotime::never);
+}
+
+
+/*-------------------------------------------------
+ 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_output_changed_cb(this, 0, param);
+}
+
+
+//-------------------------------------------------
+// set_output - set the output line state
+//-------------------------------------------------
+
+void ttl74123_device::set_output()
+{
+ int output = timer_running();
+
+ machine().scheduler().timer_set( attotime::zero, FUNC(output_callback ), output, (void *)this);
+
+ if (LOG) logerror("74123 %s: Output: %d\n", tag(), output);
+}
+
+
+/*-------------------------------------------------
+ TIMER_CALLBACK( clear_callback )
+-------------------------------------------------*/
+
+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_output_changed_cb(this, 0, output);
+}
+
+
+//-------------------------------------------------
+// start_pulse - begin timing
+//-------------------------------------------------
+
+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(0, ATTOSECONDS_PER_SECOND * m_cap * 220);
+
+ if(m_timer->elapsed() >= delay_time)
+ {
+ m_timer->adjust(duration);
+
+ if (LOG) logerror("74123 %s: Retriggering pulse. Duration: %f\n", tag(), duration.as_double());
+ }
+ else
+ {
+ if (LOG) logerror("74123 %s: Retriggering failed.\n", tag());
+ }
+ }
+ else
+ {
+ /* starting */
+ m_timer->adjust(duration);
+
+ set_output();
+
+ if (LOG) logerror("74123 %s: Starting pulse. Duration: %f\n", tag(), duration.as_double());
+ }
+}
+
+
+//-------------------------------------------------
+// a_w - write register a data
+//-------------------------------------------------
+
+WRITE8_DEVICE_HANDLER( ttl74123_a_w )
+{
+ ttl74123_device *dev = downcast<ttl74123_device *>(device);
+ dev->a_w(data);
+}
+
+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();
+ }
+
+ m_a = data;
+}
+
+
+//-------------------------------------------------
+// b_w - write register b data
+//-------------------------------------------------
+
+WRITE8_DEVICE_HANDLER( ttl74123_b_w )
+{
+ ttl74123_device *dev = downcast<ttl74123_device *>(device);
+ dev->b_w(data);
+}
+
+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();
+ }
+
+ m_b = data;
+}
+
+
+//-------------------------------------------------
+// clear_w - write register clear data
+//-------------------------------------------------
+
+WRITE8_DEVICE_HANDLER( ttl74123_clear_w )
+{
+ ttl74123_device *dev = downcast<ttl74123_device *>(device);
+ dev->clear_w(data);
+}
+
+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 */
+ {
+ m_timer->adjust(attotime::zero);
+
+ if (LOG) logerror("74123 #%s: Cleared\n", tag() );
+ }
+ m_clear = data;
+}
+
+
+//-------------------------------------------------
+// reset_w - reset device
+//-------------------------------------------------
+
+WRITE8_DEVICE_HANDLER( ttl74123_reset_w )
+{
+ ttl74123_device *dev = downcast<ttl74123_device *>(device);
+ dev->reset_w();
+}
+
+void ttl74123_device::reset_w()
+{
+ set_output();
+}