1 // license:BSD-3-Clause
2 // copyright-holders:AJR
3 /***************************************************************************
4 
5     Kawasaki Steel (Kawatetsu) KP63(A) Timer/Counter
6 
7     These macro cells provide 4 independent 16-bit down counters (reduced
8     to 3 in some versions) driven by an 8-bit prescaler attached to the
9     system clock. This prescaler is not fully emulated here, since its
10     operations are mostly transparent, though a divide-by-4 clock output
11     (SYNC) may be selected to appear on a port pin.
12 
13     Each counter has a single and optional external input (GATEn), which
14     on the KP63 can only be used to gate a divide-by-4 count but can also
15     be configured as an input clock on the KP63A.
16 
17     Two outputs are generated for each counter. The pulse or toggle output
18     (OUTPn) has configurable polarity and can be used for 8-bit PWM. The
19     strobe output (OUTSn) goes active high for 4 clock cycles when the
20     counter underflows and is connected to the interrupt controller.
21 
22     Writing the initial count register (CR) and reading the current count
23     are two-step processes, effective at the second write or first read.
24     These must not be overlapped with each other since they share a
25     temporary register.
26 
27 ***************************************************************************/
28 
29 #include "emu.h"
30 #include "kp63.h"
31 
32 #define VERBOSE 1
33 #include "logmacro.h"
34 
35 
36 //**************************************************************************
37 //  GLOBAL VARIABLES
38 //**************************************************************************
39 
40 // device type definitions
41 DEFINE_DEVICE_TYPE(KP63_3CHANNEL, kp63_3channel_device, "kp63_3channel", "Kawasaki Steel KP63 Timer/Counter (3 channels)")
42 DEFINE_DEVICE_TYPE(KP63A, kp63a_device, "kp63a", "Kawasaki Steel KP63A Timer/Counter")
43 
44 const char *const kp63_device::s_count_modes[4] =
45 {
46 	"one-shot",
47 	"continuous count",
48 	"WDT",
49 	"PWM"
50 };
51 
52 
53 //**************************************************************************
54 //  KP63 DEVICE
55 //**************************************************************************
56 
57 //-------------------------------------------------
58 //  kp63_device - constructor
59 //-------------------------------------------------
60 
kp63_device(const machine_config & mconfig,device_type type,const char * tag,device_t * owner,u32 clock,u8 num_counters,u8 mode_mask)61 kp63_device::kp63_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, u32 clock, u8 num_counters, u8 mode_mask)
62 	: device_t(mconfig, type, tag, owner, clock)
63 	, m_out_pulse_callback(*this)
64 	, m_out_strobe_callback(*this)
65 	, c_num_counters(num_counters)
66 	, c_mode_mask(mode_mask)
67 	, m_timer{0}
68 	, m_strobe_timer{0}
69 	, m_pwm_timer{0}
70 	, m_cr{0}
71 	, m_last_count{0}
72 	, m_count_tmp{0}
73 	, m_status{0}
74 	, m_rw_seq(0)
75 	, m_timer_started(0)
76 	, m_gate_input(0xf)
77 {
78 }
79 
80 
81 //-------------------------------------------------
82 //  kp63_3channel_device - constructor
83 //-------------------------------------------------
84 
kp63_3channel_device(const machine_config & mconfig,const char * tag,device_t * owner,u32 clock)85 kp63_3channel_device::kp63_3channel_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock)
86 	: kp63_device(mconfig, KP63_3CHANNEL, tag, owner, clock, 3, 0x1f)
87 {
88 }
89 
90 
91 //-------------------------------------------------
92 //  kp63a_device - constructor
93 //-------------------------------------------------
94 
kp63a_device(const machine_config & mconfig,const char * tag,device_t * owner,u32 clock)95 kp63a_device::kp63a_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock)
96 	: kp63_device(mconfig, KP63A, tag, owner, clock, 4, 0x3f)
97 {
98 }
99 
100 
101 //-------------------------------------------------
102 //  device_resolve_objects - resolve objects that
103 //  may be needed for other devices to set
104 //  initial conditions at start time
105 //-------------------------------------------------
106 
device_resolve_objects()107 void kp63_device::device_resolve_objects()
108 {
109 	// Resolve output callbacks
110 	m_out_pulse_callback.resolve_all_safe();
111 	m_out_strobe_callback.resolve_all_safe();
112 }
113 
114 
115 //-------------------------------------------------
116 //  timer_expired - handle timed count underflow
117 //-------------------------------------------------
118 
119 template <int N>
TIMER_CALLBACK_MEMBER(kp63_device::timer_expired)120 TIMER_CALLBACK_MEMBER(kp63_device::timer_expired)
121 {
122 	timer_pulse(N);
123 }
124 
125 
126 //-------------------------------------------------
127 //  strobe_off - handle end of strobe output
128 //-------------------------------------------------
129 
130 template <int N>
TIMER_CALLBACK_MEMBER(kp63_device::strobe_off)131 TIMER_CALLBACK_MEMBER(kp63_device::strobe_off)
132 {
133 	m_out_strobe_callback[N](0);
134 }
135 
136 
137 //-------------------------------------------------
138 //  pwm_off - handle PWM phase change
139 //-------------------------------------------------
140 
141 template <int N>
TIMER_CALLBACK_MEMBER(kp63_device::pwm_off)142 TIMER_CALLBACK_MEMBER(kp63_device::pwm_off)
143 {
144 	m_status[N] &= 0x7f;
145 	m_out_pulse_callback[N](BIT(m_status[N], 4) ? 1 : 0);
146 }
147 
148 
149 //-------------------------------------------------
150 //  device_start - device-specific startup
151 //-------------------------------------------------
152 
device_start()153 void kp63_device::device_start()
154 {
155 	// Setup timers
156 	m_timer[0] = machine().scheduler().timer_alloc(timer_expired_delegate(FUNC(kp63_device::timer_expired<0>), this));
157 	m_strobe_timer[0] = machine().scheduler().timer_alloc(timer_expired_delegate(FUNC(kp63_device::strobe_off<0>), this));
158 	m_pwm_timer[0] = machine().scheduler().timer_alloc(timer_expired_delegate(FUNC(kp63_device::pwm_off<0>), this));
159 	m_timer[1] = machine().scheduler().timer_alloc(timer_expired_delegate(FUNC(kp63_device::timer_expired<1>), this));
160 	m_strobe_timer[1] = machine().scheduler().timer_alloc(timer_expired_delegate(FUNC(kp63_device::strobe_off<1>), this));
161 	m_pwm_timer[1] = machine().scheduler().timer_alloc(timer_expired_delegate(FUNC(kp63_device::pwm_off<1>), this));
162 	m_timer[2] = machine().scheduler().timer_alloc(timer_expired_delegate(FUNC(kp63_device::timer_expired<2>), this));
163 	m_strobe_timer[2] = machine().scheduler().timer_alloc(timer_expired_delegate(FUNC(kp63_device::strobe_off<2>), this));
164 	m_pwm_timer[2] = machine().scheduler().timer_alloc(timer_expired_delegate(FUNC(kp63_device::pwm_off<2>), this));
165 	if (c_num_counters > 3)
166 	{
167 		m_timer[3] = machine().scheduler().timer_alloc(timer_expired_delegate(FUNC(kp63_device::timer_expired<3>), this));
168 		m_strobe_timer[3] = machine().scheduler().timer_alloc(timer_expired_delegate(FUNC(kp63_device::strobe_off<3>), this));
169 		m_pwm_timer[3] = machine().scheduler().timer_alloc(timer_expired_delegate(FUNC(kp63_device::pwm_off<3>), this));
170 	}
171 
172 	// Save state
173 	save_item(NAME(m_cr));
174 	save_item(NAME(m_last_count));
175 	save_item(NAME(m_count_tmp));
176 	save_item(NAME(m_status));
177 	save_item(NAME(m_rw_seq));
178 	save_item(NAME(m_timer_started));
179 	save_item(NAME(m_gate_input));
180 }
181 
182 
183 //-------------------------------------------------
184 //  device_reset - device-specific reset
185 //-------------------------------------------------
186 
device_reset()187 void kp63_device::device_reset()
188 {
189 	for (unsigned n = 0; n < c_num_counters; n++)
190 	{
191 		// Turn off timers
192 		m_timer[n]->adjust(attotime::never);
193 		m_strobe_timer[n]->adjust(attotime::never);
194 		m_pwm_timer[n]->adjust(attotime::never);
195 
196 		// Reset status and count
197 		m_status[n] = 0;
198 		m_cr[n] = 0xffff;
199 		m_last_count[n] = 0xffff;
200 
201 		// Clear outputs
202 		m_out_pulse_callback[n](0);
203 		m_out_strobe_callback[n](0);
204 	}
205 
206 	// Clear read/write sequence for all counters
207 	m_rw_seq = 0;
208 	m_timer_started = 0;
209 }
210 
211 
212 //-------------------------------------------------
213 //  timer_pulse - change outputs and stop or
214 //  reload timer as count underflows
215 //-------------------------------------------------
216 
timer_pulse(unsigned n)217 void kp63_device::timer_pulse(unsigned n)
218 {
219 	// Toggle pulse output
220 	m_status[n] ^= 0x80;
221 	m_out_pulse_callback[n](BIT(m_status[n], 7) != BIT(m_status[n], 4) ? 1 : 0);
222 
223 	// Begin strobe output
224 	m_out_strobe_callback[n](1);
225 	m_strobe_timer[n]->adjust(clocks_to_attotime(4));
226 
227 	// Reload timer in continuous count and PWM modes
228 	if (BIT(m_status[n], 2))
229 		timer_reload(n);
230 	else
231 	{
232 		// Stop count at FFFF in one-shot and WDT modes
233 		m_last_count[n] = 0xffff;
234 		m_timer_started &= ~(1 << n);
235 	}
236 }
237 
238 
239 //-------------------------------------------------
240 //  timer_reload - reload timer from CR
241 //-------------------------------------------------
242 
timer_reload(unsigned n)243 void kp63_device::timer_reload(unsigned n)
244 {
245 	m_timer_started |= 1 << n;
246 
247 	if (BIT(m_status[n], 5) || ((m_status[n] & 0x03) == 0x03 && !BIT(m_gate_input, n)))
248 		m_last_count[n] = m_cr[n];
249 	else
250 	{
251 		unsigned prescale = BIT(m_status[n], 1) ? 4 : BIT(m_status[n], 0) ? 16 : 256;
252 		if ((m_status[n] & 0x0c) == 0x0c)
253 		{
254 			// PWM
255 			m_timer[n]->adjust(clocks_to_attotime(prescale * ((m_cr[n] & 0x00ff) + 1)));
256 			m_pwm_timer[n]->adjust(clocks_to_attotime(prescale * ((m_cr[n] >> 8) + 1)));
257 		}
258 		else
259 			m_timer[n]->adjust(clocks_to_attotime(prescale * (u32(m_cr[n]) + 1)));
260 	}
261 }
262 
263 
264 //-------------------------------------------------
265 //  timer_resume_count - start counting again
266 //-------------------------------------------------
267 
timer_resume_count(unsigned n)268 void kp63_device::timer_resume_count(unsigned n)
269 {
270 	if (!BIT(m_status[n], 5) || ((m_status[n] & 0x03) != 0x03 || BIT(m_gate_input, n)))
271 	{
272 		unsigned prescale = BIT(m_status[n], 1) ? 4 : BIT(m_status[n], 0) ? 16 : 256;
273 		if ((m_status[n] & 0x0c) == 0x0c)
274 		{
275 			// PWM
276 			m_timer[n]->adjust(clocks_to_attotime(prescale * ((m_last_count[n] & 0x00ff) + 1)));
277 			m_pwm_timer[n]->adjust(clocks_to_attotime(prescale * ((m_last_count[n] >> 8) + 1)));
278 		}
279 		else
280 			m_timer[n]->adjust(clocks_to_attotime(prescale * (u32(m_last_count[n]) + 1)));
281 	}
282 }
283 
284 
285 //-------------------------------------------------
286 //  timer_get_count - obtain the instant count in
287 //  case of a readout or pause
288 //-------------------------------------------------
289 
timer_get_count(unsigned n) const290 u16 kp63_device::timer_get_count(unsigned n) const
291 {
292 	if (!BIT(m_timer_started, n) || BIT(m_status[n], 5) || ((m_status[n] & 0x03) == 0x03 && !BIT(m_gate_input, n)))
293 		return m_last_count[n];
294 	else
295 	{
296 		unsigned prescale = BIT(m_status[n], 1) ? 4 : BIT(m_status[n], 0) ? 16 : 256;
297 		if ((m_status[n] & 0x0c) == 0x0c)
298 		{
299 			// PWM
300 			u8 ticks = attotime_to_clocks(m_timer[n]->remaining()) / prescale;
301 			return ticks | ((m_cr[n] - (u16(ticks) << 8)) & 0xff00);
302 		}
303 		else
304 			return attotime_to_clocks(m_timer[n]->remaining()) / prescale;
305 	}
306 }
307 
308 
309 //-------------------------------------------------
310 //  read - read count or status register
311 //-------------------------------------------------
312 
read(offs_t offset)313 u8 kp63_device::read(offs_t offset)
314 {
315 	const unsigned n = offset >> 1;
316 	assert(n < c_num_counters);
317 
318 	if (BIT(offset, 0))
319 	{
320 		// Status read clears read/write sequence
321 		if (!machine().side_effects_disabled())
322 			m_rw_seq &= ~(1 << n);
323 		return m_status[n];
324 	}
325 	else if (BIT(m_rw_seq, n))
326 	{
327 		// Second step of counter readout
328 		if (!machine().side_effects_disabled())
329 			m_rw_seq &= ~(1 << n);
330 		return m_count_tmp[n];
331 	}
332 	else
333 	{
334 		// First step of counter readout
335 		u16 count = timer_get_count(n);
336 		if (!machine().side_effects_disabled())
337 		{
338 			// Latch high byte into TMP register
339 			m_rw_seq |= 1 << n;
340 			m_count_tmp[n] = count >> 8;
341 		}
342 		return count & 0x00ff;
343 	}
344 }
345 
346 //-------------------------------------------------
347 //  write - set CR or mode register
348 //-------------------------------------------------
349 
write(offs_t offset,u8 data)350 void kp63_device::write(offs_t offset, u8 data)
351 {
352 	const unsigned n = offset >> 1;
353 	assert(n < c_num_counters);
354 
355 	if (BIT(offset, 0))
356 	{
357 		bool old_outp = BIT(m_status[n], 7) != BIT(m_status[n], 4);
358 
359 		// Stop count before setting mode
360 		if (BIT(m_timer_started, n))
361 		{
362 			if (!BIT(m_status[n], 5) || ((m_status[n] & 0x03) != 0x03 || BIT(m_gate_input, n)))
363 			{
364 				m_last_count[n] = timer_get_count(n);
365 				m_timer[n]->adjust(attotime::never);
366 				m_pwm_timer[n]->adjust(attotime::never);
367 			}
368 			m_timer_started &= ~(1 << n);
369 		}
370 
371 		if (BIT(data & c_mode_mask, 5))
372 			LOG("%s: Timer #%d configured for %s mode, %s edges of GATE, initial output %c\n",
373 				machine().describe_context(),
374 				n,
375 				s_count_modes[BIT(data, 2, 2)],
376 				BIT(data, 1) ? "???" : BIT(data, 0) ? "falling" : "rising",
377 				BIT(data, 4) ? 'H' : 'L');
378 		else
379 			LOG("%s: Timer #%d configured for %s mode, 1/%d system clock (GATE %s), initial output %c\n",
380 				machine().describe_context(),
381 				n,
382 				s_count_modes[BIT(data, 2, 2)],
383 				BIT(data, 1) ? 4 : BIT(data, 0) ? 16 : 256,
384 				(data & 0x03) == 0x03 ? "effective" : "ignored",
385 				BIT(data, 4) ? 'H' : 'L');
386 		m_status[n] = data & c_mode_mask;
387 
388 		// Update OUTP
389 		if (old_outp != BIT(data, 4))
390 			m_out_pulse_callback[n](BIT(data, 4) ? 1 : 0);
391 	}
392 	else if ((m_status[n] & 0x0c) == 0x08)
393 	{
394 		// WDT retrigger (data ignored; initial count must be written using a different mode)
395 		timer_reload(n);
396 	}
397 	else if (BIT(m_rw_seq, n))
398 	{
399 		// Second step of initial count write
400 		m_rw_seq &= ~(1 << n);
401 		m_cr[n] = u16(data) << 8 | m_count_tmp[n];
402 
403 		LOG("%s: Timer #%d initial count = %d\n", machine().describe_context(), n, (m_status[n] == 0x0c) ? m_cr[n] & 0x00ff : m_cr[n]);
404 
405 		// Automatic retrigger in one-shot and continuous modes
406 		if (!BIT(m_status[n], 3) || !BIT(m_timer_started, n))
407 		{
408 			if (!BIT(m_status[n], 7))
409 			{
410 				// Toggle OUTP
411 				m_status[n] |= 0x80;
412 				m_out_pulse_callback[n](BIT(m_status[n], 4) ? 0 : 1);
413 			}
414 			timer_reload(n);
415 		}
416 	}
417 	else
418 	{
419 		// First step of initial count write (held in TMP register)
420 		m_rw_seq |= 1 << n;
421 		m_count_tmp[n] = data;
422 	}
423 }
424 
425 //-------------------------------------------------
426 //  write_gate - handle gate inputs
427 //-------------------------------------------------
428 
write_gate(unsigned n,bool state)429 void kp63_device::write_gate(unsigned n, bool state)
430 {
431 	assert(n < c_num_counters);
432 
433 	if (BIT(m_gate_input, n) != state)
434 		return;
435 
436 	if (state)
437 		m_gate_input |= 1 << n;
438 	else
439 		m_gate_input &= ~(1 << n);
440 
441 	if (BIT(m_timer_started, n))
442 	{
443 		if ((m_status[n] & 0x23) == 0x03)
444 		{
445 			// Timer gated on or off
446 			if (state)
447 				timer_resume_count(n);
448 			else
449 			{
450 				m_last_count[n] = timer_get_count(n);
451 				m_timer[n]->adjust(attotime::never);
452 			}
453 		}
454 		else if ((m_status[n] & 0x23) == (state ? 0x21 : 0x20))
455 		{
456 			// Count edges of gate input
457 			if ((m_status[n] & 0x0c) == 0x0c)
458 			{
459 				// PWM: count is in lower 8 bits
460 				if ((m_last_count[n] & 0x00ff) == 0)
461 					timer_pulse(n);
462 				else
463 				{
464 					// Decrement both halves and check for underflow in upper half
465 					m_last_count[n] -= 0x0101;
466 					if (m_last_count[n] >= 0xff00)
467 					{
468 						m_status[n] &= 0x7f;
469 						m_out_pulse_callback[n](BIT(m_status[n], 4) ? 1 : 0);
470 					}
471 				}
472 			}
473 			else if (m_last_count[n]-- == 0)
474 				timer_pulse(n);
475 		}
476 	}
477 }
478