summaryrefslogtreecommitdiffstatshomepage
path: root/src/devices/machine/74123.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/devices/machine/74123.c')
-rw-r--r--src/devices/machine/74123.c249
1 files changed, 249 insertions, 0 deletions
diff --git a/src/devices/machine/74123.c b/src/devices/machine/74123.c
new file mode 100644
index 00000000000..f88b71dfab8
--- /dev/null
+++ b/src/devices/machine/74123.c
@@ -0,0 +1,249 @@
+// license:BSD-3-Clause
+// copyright-holders:Couriersud
+/*****************************************************************************
+
+ 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, "74123 TTL", tag, owner, clock, "ttl74123", __FILE__),
+ 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),
+ m_output_changed_cb(*this)
+{
+}
+
+//-------------------------------------------------
+// device_start - device-specific startup
+//-------------------------------------------------
+
+void ttl74123_device::device_start()
+{
+ m_output_changed_cb.resolve_safe();
+
+ m_timer = machine().scheduler().timer_alloc(timer_expired_delegate(FUNC(ttl74123_device::clear_callback),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_MEMBER( ttl74123_device::output_callback )
+{
+ m_output_changed_cb((offs_t)0, param);
+}
+
+
+//-------------------------------------------------
+// set_output - set the output line state
+//-------------------------------------------------
+
+void ttl74123_device::set_output()
+{
+ int output = timer_running();
+
+ machine().scheduler().timer_set( attotime::zero, timer_expired_delegate(FUNC(ttl74123_device::output_callback ),this), output);
+
+ if (LOG) logerror("74123 %s: Output: %d\n", tag(), output);
+}
+
+
+/*-------------------------------------------------
+ TIMER_CALLBACK( clear_callback )
+-------------------------------------------------*/
+
+TIMER_CALLBACK_MEMBER( ttl74123_device::clear_callback )
+{
+ int output = timer_running();
+
+ m_output_changed_cb((offs_t)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_MEMBER( ttl74123_device::a_w )
+{
+ /* 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_MEMBER( ttl74123_device::b_w)
+{
+ /* 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_MEMBER( ttl74123_device::clear_w)
+{
+ /* 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_MEMBER( ttl74123_device::reset_w)
+{
+ set_output();
+}