1 // license:BSD-3-Clause
2 // copyright-holders:Couriersud
3 /*****************************************************************************
4
5 74123 monoflop emulator - see 74123.h for pin out and truth table
6
7 Formulas came from the TI datasheet revised on March 1998
8
9 *****************************************************************************/
10
11 #include "emu.h"
12 #include "machine/74123.h"
13 #include "machine/rescap.h"
14
15 //#define VERBOSE 1
16 #include "logmacro.h"
17
18
19 //**************************************************************************
20 // LIVE DEVICE
21 //**************************************************************************
22
23 // device type definition
24 DEFINE_DEVICE_TYPE(TTL74123, ttl74123_device, "ttl74123", "74123 TTL")
25
26 //-------------------------------------------------
27 // ttl74123_device - constructor
28 //-------------------------------------------------
29
ttl74123_device(const machine_config & mconfig,const char * tag,device_t * owner,uint32_t clock)30 ttl74123_device::ttl74123_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
31 : device_t(mconfig, TTL74123, tag, owner, clock),
32 m_timer(nullptr),
33 m_connection_type(TTL74123_NOT_GROUNDED_NO_DIODE),
34 m_res(1.0),
35 m_cap(1.0),
36 m_a(0),
37 m_b(0),
38 m_clear(0),
39 m_output_changed_cb(*this)
40 {
41 }
42
43 //-------------------------------------------------
44 // device_start - device-specific startup
45 //-------------------------------------------------
46
device_start()47 void ttl74123_device::device_start()
48 {
49 m_output_changed_cb.resolve_safe();
50
51 m_timer = machine().scheduler().timer_alloc(timer_expired_delegate(FUNC(ttl74123_device::clear_callback),this));
52
53 /* register for state saving */
54 save_item(NAME(m_a));
55 save_item(NAME(m_b));
56 save_item(NAME(m_clear));
57 }
58
59
60 //-------------------------------------------------
61 // device_reset - device-specific reset
62 //-------------------------------------------------
63
device_reset()64 void ttl74123_device::device_reset()
65 {
66 set_output();
67 }
68
69
70
71 //-------------------------------------------------
72 // compute_duration - compute timer duration
73 //-------------------------------------------------
74
compute_duration()75 attotime ttl74123_device::compute_duration()
76 {
77 double duration;
78
79 switch (m_connection_type)
80 {
81 case TTL74123_NOT_GROUNDED_NO_DIODE:
82 duration = 0.28 * m_res * m_cap * (1.0 + (700.0 / m_res));
83 break;
84
85 case TTL74123_NOT_GROUNDED_DIODE:
86 duration = 0.25 * m_res * m_cap * (1.0 + (700.0 / m_res));
87 break;
88
89 case TTL74123_GROUNDED:
90 default:
91 if (m_cap < CAP_U(0.1))
92 {
93 /* this is really a curve - a very flat one in the 0.1uF-.01uF range */
94 duration = 0.32 * m_res * m_cap;
95 }
96 else
97 {
98 duration = 0.33 * m_res * m_cap;
99 }
100 break;
101 }
102
103 return attotime::from_double(duration);
104 }
105
106
107 //-------------------------------------------------
108 // timer_running - is the timer running?
109 //-------------------------------------------------
110
timer_running()111 int ttl74123_device::timer_running()
112 {
113 return (m_timer->remaining() > attotime::zero) &&
114 (m_timer->remaining() != attotime::never);
115 }
116
117
118 /*-------------------------------------------------
119 TIMER_CALLBACK_MEMBER( output_callback )
120 -------------------------------------------------*/
121
TIMER_CALLBACK_MEMBER(ttl74123_device::output_callback)122 TIMER_CALLBACK_MEMBER( ttl74123_device::output_callback )
123 {
124 m_output_changed_cb(param);
125 }
126
127
128 //-------------------------------------------------
129 // set_output - set the output line state
130 //-------------------------------------------------
131
set_output()132 void ttl74123_device::set_output()
133 {
134 int output = timer_running();
135
136 machine().scheduler().timer_set( attotime::zero, timer_expired_delegate(FUNC(ttl74123_device::output_callback ),this), output);
137
138 LOG("74123: Output: %d\n", output);
139 }
140
141
142 /*-------------------------------------------------
143 TIMER_CALLBACK_MEMBER( clear_callback )
144 -------------------------------------------------*/
145
TIMER_CALLBACK_MEMBER(ttl74123_device::clear_callback)146 TIMER_CALLBACK_MEMBER( ttl74123_device::clear_callback )
147 {
148 int output = timer_running();
149
150 m_output_changed_cb(output);
151 }
152
153 //-------------------------------------------------
154 // start_pulse - begin timing
155 //-------------------------------------------------
156
start_pulse()157 void ttl74123_device::start_pulse()
158 {
159 attotime duration = compute_duration();
160
161 if(timer_running())
162 {
163 /* retriggering, but not if we are called to quickly */
164 attotime delay_time = attotime(0, ATTOSECONDS_PER_SECOND * m_cap * 220);
165
166 if(m_timer->elapsed() >= delay_time)
167 {
168 m_timer->adjust(duration);
169
170 LOG("74123: Retriggering pulse. Duration: %f\n", duration.as_double());
171 }
172 else
173 {
174 LOG("74123: Retriggering failed.\n");
175 }
176 }
177 else
178 {
179 /* starting */
180 m_timer->adjust(duration);
181
182 set_output();
183
184 LOG("74123: Starting pulse. Duration: %f\n", duration.as_double());
185 }
186 }
187
188
189 //-------------------------------------------------
190 // a_w - write register a data
191 //-------------------------------------------------
192
WRITE_LINE_MEMBER(ttl74123_device::a_w)193 WRITE_LINE_MEMBER( ttl74123_device::a_w )
194 {
195 /* start/regtrigger pulse if B=HI and falling edge on A (while clear is HI) */
196 if (!state && m_a && m_b && m_clear)
197 {
198 start_pulse();
199 }
200
201 m_a = state;
202 }
203
204
205 //-------------------------------------------------
206 // b_w - write register b data
207 //-------------------------------------------------
208
WRITE_LINE_MEMBER(ttl74123_device::b_w)209 WRITE_LINE_MEMBER( ttl74123_device::b_w)
210 {
211 /* start/regtrigger pulse if A=LO and rising edge on B (while clear is HI) */
212 if (state && !m_b && !m_a && m_clear)
213 {
214 start_pulse();
215 }
216
217 m_b = state;
218 }
219
220
221 //-------------------------------------------------
222 // clear_w - write register clear data
223 //-------------------------------------------------
224
WRITE_LINE_MEMBER(ttl74123_device::clear_w)225 WRITE_LINE_MEMBER( ttl74123_device::clear_w)
226 {
227 /* start/regtrigger pulse if B=HI and A=LO and rising edge on clear */
228 if (state && !m_a && m_b && !m_clear)
229 {
230 start_pulse();
231 }
232 else if (!state) /* clear the output */
233 {
234 m_timer->adjust(attotime::zero);
235
236 LOG("74123: Cleared\n");
237 }
238 m_clear = state;
239 }
240
241
242 //-------------------------------------------------
243 // reset_w - reset device
244 //-------------------------------------------------
245
WRITE_LINE_MEMBER(ttl74123_device::reset_w)246 WRITE_LINE_MEMBER( ttl74123_device::reset_w)
247 {
248 set_output();
249 }
250