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