1 // license:BSD-3-Clause
2 // copyright-holders:Olivier Galibert
3 #include "emu.h"
4 #include "h8_timer16.h"
5 
6 // Verbosity level
7 // 0 = no messages
8 // 1 = everything
9 const int V = 0;
10 
11 DEFINE_DEVICE_TYPE(H8_TIMER16,          h8_timer16_device,          "h8_timer16",          "H8 16-bit timer")
12 DEFINE_DEVICE_TYPE(H8_TIMER16_CHANNEL,  h8_timer16_channel_device,  "h8_timer16_channel",  "H8 16-bit timer channel")
13 DEFINE_DEVICE_TYPE(H8H_TIMER16_CHANNEL, h8h_timer16_channel_device, "h8h_timer16_channel", "H8H 16-bit timer channel")
14 DEFINE_DEVICE_TYPE(H8S_TIMER16_CHANNEL, h8s_timer16_channel_device, "h8s_timer16_channel", "H8S 16-bit timer channel")
15 
h8_timer16_channel_device(const machine_config & mconfig,const char * tag,device_t * owner,uint32_t clock)16 h8_timer16_channel_device::h8_timer16_channel_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) :
17 	h8_timer16_channel_device(mconfig, H8_TIMER16_CHANNEL, tag, owner, clock)
18 {
19 	chain_tag = nullptr;
20 }
21 
h8_timer16_channel_device(const machine_config & mconfig,device_type type,const char * tag,device_t * owner,uint32_t clock)22 h8_timer16_channel_device::h8_timer16_channel_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock) :
23 	device_t(mconfig, type, tag, owner, clock),
24 	cpu(*this, "^^"), chained_timer(nullptr), intc(nullptr), intc_tag(nullptr), tier_mask(0), tgr_count(0), tbr_count(0), tgr_clearing(0), tcr(0), tier(0), ier(0), isr(0), clock_type(0),
25 	clock_divider(0), tcnt(0), last_clock_update(0), event_time(0), phase(0), counter_cycle(0), counter_incrementing(false), channel_active(false)
26 {
27 	chain_tag = nullptr;
28 }
29 
set_info(int _tgr_count,int _tbr_count,const char * intc,int irq_base)30 void h8_timer16_channel_device::set_info(int _tgr_count, int _tbr_count, const char *intc, int irq_base)
31 {
32 	tgr_count = _tgr_count;
33 	tbr_count = _tbr_count;
34 	intc_tag = intc;
35 
36 	interrupt[0] = irq_base++;
37 	interrupt[1] = irq_base++;
38 	interrupt[2] = -1;
39 	interrupt[3] = -1;
40 	interrupt[4] = irq_base;
41 	interrupt[5] = irq_base;
42 }
43 
tcr_r()44 uint8_t h8_timer16_channel_device::tcr_r()
45 {
46 	return tcr;
47 }
48 
tcr_w(uint8_t data)49 void h8_timer16_channel_device::tcr_w(uint8_t data)
50 {
51 	update_counter();
52 	tcr = data;
53 	if(V>=1) logerror("tcr_w %02x\n", data);
54 	tcr_update();
55 	recalc_event();
56 }
57 
tmdr_r()58 uint8_t h8_timer16_channel_device::tmdr_r()
59 {
60 	return 0x00;
61 }
62 
tmdr_w(uint8_t data)63 void h8_timer16_channel_device::tmdr_w(uint8_t data)
64 {
65 	if(V>=1) logerror("tmdr_w %02x\n", data);
66 }
67 
tior_r()68 uint8_t h8_timer16_channel_device::tior_r()
69 {
70 	return 0x00;
71 }
72 
tior_w(offs_t offset,uint8_t data)73 void h8_timer16_channel_device::tior_w(offs_t offset, uint8_t data)
74 {
75 	if(V>=1) logerror("tior_w %d, %02x\n", offset, data);
76 }
77 
set_ier(uint8_t value)78 void h8_timer16_channel_device::set_ier(uint8_t value)
79 {
80 	update_counter();
81 	ier = value;
82 	recalc_event();
83 }
84 
set_enable(bool enable)85 void h8_timer16_channel_device::set_enable(bool enable)
86 {
87 	update_counter();
88 	channel_active = enable;
89 	recalc_event();
90 }
91 
tier_r()92 uint8_t h8_timer16_channel_device::tier_r()
93 {
94 	return tier;
95 }
96 
tier_w(uint8_t data)97 void h8_timer16_channel_device::tier_w(uint8_t data)
98 {
99 	update_counter();
100 	if(V>=1) logerror("tier_w %02x\n", data);
101 	tier = data;
102 	tier_update();
103 	if(V>=1) logerror("irq %c%c%c%c%c%c trigger=%d\n",
104 						ier & IRQ_A ? 'a' : '.',
105 						ier & IRQ_B ? 'b' : '.',
106 						ier & IRQ_C ? 'c' : '.',
107 						ier & IRQ_D ? 'd' : '.',
108 						ier & IRQ_V ? 'v' : '.',
109 						ier & IRQ_U ? 'u' : '.',
110 						ier & IRQ_TRIG ? 1 : 0);
111 	recalc_event();
112 }
113 
tsr_r()114 uint8_t h8_timer16_channel_device::tsr_r()
115 {
116 	return isr_to_sr();
117 }
118 
tsr_w(uint8_t data)119 void h8_timer16_channel_device::tsr_w(uint8_t data)
120 {
121 	if(V>=1) logerror("tsr_w %02x\n", data);
122 	isr_update(data);
123 }
124 
tcnt_r()125 uint16_t h8_timer16_channel_device::tcnt_r()
126 {
127 	update_counter();
128 	return tcnt;
129 }
130 
tcnt_w(offs_t offset,uint16_t data,uint16_t mem_mask)131 void h8_timer16_channel_device::tcnt_w(offs_t offset, uint16_t data, uint16_t mem_mask)
132 {
133 	update_counter();
134 	COMBINE_DATA(&tcnt);
135 	if(V>=1) logerror("tcnt_w %04x\n", tcnt);
136 	recalc_event();
137 }
138 
tgr_r(offs_t offset)139 uint16_t h8_timer16_channel_device::tgr_r(offs_t offset)
140 {
141 	return tgr[offset];
142 }
143 
tgr_w(offs_t offset,uint16_t data,uint16_t mem_mask)144 void h8_timer16_channel_device::tgr_w(offs_t offset, uint16_t data, uint16_t mem_mask)
145 {
146 	update_counter();
147 	COMBINE_DATA(tgr + offset);
148 	if(V>=1) logerror("tgr%c_w %04x\n", 'a'+offset, tgr[offset]);
149 	recalc_event();
150 }
151 
tbr_r(offs_t offset)152 uint16_t h8_timer16_channel_device::tbr_r(offs_t offset)
153 {
154 	return tgr[offset+tgr_count];
155 }
156 
tbr_w(offs_t offset,uint16_t data,uint16_t mem_mask)157 void h8_timer16_channel_device::tbr_w(offs_t offset, uint16_t data, uint16_t mem_mask)
158 {
159 	COMBINE_DATA(tgr + offset + tgr_count);
160 	if(V>=1) logerror("tbr%c_w %04x\n", 'a'+offset, tgr[offset]);
161 }
162 
device_start()163 void h8_timer16_channel_device::device_start()
164 {
165 	intc = owner()->siblingdevice<h8_intc_device>(intc_tag);
166 	channel_active = false;
167 	device_reset();
168 
169 	save_item(NAME(tgr_clearing));
170 	save_item(NAME(tcr));
171 	save_item(NAME(tier));
172 	save_item(NAME(ier));
173 	save_item(NAME(isr));
174 	save_item(NAME(clock_type));
175 	save_item(NAME(clock_divider));
176 	save_item(NAME(tcnt));
177 	save_item(NAME(tgr));
178 	save_item(NAME(last_clock_update));
179 	save_item(NAME(event_time));
180 	save_item(NAME(phase));
181 	save_item(NAME(counter_cycle));
182 	save_item(NAME(counter_incrementing));
183 	save_item(NAME(channel_active));
184 }
185 
device_reset()186 void h8_timer16_channel_device::device_reset()
187 {
188 	// Don't touch channel_active here, top level device handles it
189 	tcr = 0;
190 	tcnt = 0;
191 	memset(tgr, 0xff, sizeof(tgr));
192 	tgr_clearing = TGR_CLEAR_NONE;
193 	clock_type = DIV_1;
194 	clock_divider = 0;
195 	counter_cycle = 0x10000;
196 	phase = 0;
197 	tier = 0x40 & tier_mask;
198 	ier = 0;
199 	isr = 0;
200 	last_clock_update = 0;
201 	event_time = 0;
202 	counter_incrementing = true;
203 }
204 
internal_update(uint64_t current_time)205 uint64_t h8_timer16_channel_device::internal_update(uint64_t current_time)
206 {
207 	if(event_time && current_time >= event_time) {
208 		update_counter(current_time);
209 		recalc_event(current_time);
210 	}
211 
212 	return event_time;
213 }
214 
update_counter(uint64_t cur_time)215 void h8_timer16_channel_device::update_counter(uint64_t cur_time)
216 {
217 	if(clock_type != DIV_1)
218 		return;
219 
220 	if(!cur_time)
221 		cur_time = cpu->total_cycles();
222 
223 	if(!channel_active) {
224 		last_clock_update = cur_time;
225 		return;
226 	}
227 
228 	uint64_t base_time = last_clock_update;
229 	uint64_t new_time = cur_time;
230 	if(clock_divider) {
231 		base_time = (base_time + phase) >> clock_divider;
232 		new_time = (new_time + phase) >> clock_divider;
233 	}
234 	if(counter_incrementing) {
235 		int tt = tcnt + new_time - base_time;
236 		tcnt = tt % counter_cycle;
237 
238 		for(int i=0; i<tgr_count; i++)
239 			if((ier & (1 << i)) && (tt == tgr[i] || tcnt == tgr[i]) && interrupt[i] != -1) {
240 				isr |= 1 << i;
241 				intc->internal_interrupt(interrupt[i]);
242 			}
243 		if(tt >= 0x10000 && (ier & IRQ_V) && interrupt[4] != -1) {
244 			isr |= IRQ_V;
245 			intc->internal_interrupt(interrupt[4]);
246 		}
247 	} else
248 		tcnt = (((tcnt ^ 0xffff) + new_time - base_time) % counter_cycle) ^ 0xffff;
249 	last_clock_update = cur_time;
250 }
251 
recalc_event(uint64_t cur_time)252 void h8_timer16_channel_device::recalc_event(uint64_t cur_time)
253 {
254 	if(!channel_active) {
255 		event_time = 0;
256 		return;
257 	}
258 
259 	bool update_cpu = cur_time == 0;
260 	uint64_t old_event_time = event_time;
261 
262 	if(clock_type != DIV_1) {
263 		event_time = 0;
264 		if(old_event_time && update_cpu)
265 			cpu->internal_update();
266 
267 		return;
268 	}
269 
270 	if(!cur_time)
271 		cur_time = cpu->total_cycles();
272 
273 	if(counter_incrementing) {
274 		uint32_t event_delay = 0xffffffff;
275 		if(tgr_clearing >= 0 && tgr[tgr_clearing])
276 			counter_cycle = tgr[tgr_clearing];
277 		else {
278 			counter_cycle = 0x10000;
279 			if(ier & IRQ_V) {
280 				event_delay = counter_cycle - tcnt;
281 				if(!event_delay)
282 					event_delay = counter_cycle;
283 			}
284 		}
285 		for(int i=0; i<tgr_count; i++)
286 			if(ier & (1 << i)) {
287 				uint32_t new_delay = 0xffffffff;
288 				if(tgr[i] > tcnt) {
289 					if(tcnt >= counter_cycle || tgr[i] <= counter_cycle)
290 						new_delay = tgr[i] - tcnt;
291 				} else if(tgr[i] <= counter_cycle) {
292 					if(tcnt < counter_cycle)
293 						new_delay = (counter_cycle - tcnt) + tgr[i];
294 					else
295 						new_delay = (0x10000 - tcnt) + tgr[i];
296 				}
297 
298 				if(event_delay > new_delay)
299 					event_delay = new_delay;
300 			}
301 
302 		if(event_delay != 0xffffffff)
303 			event_time = ((((cur_time + (1ULL << clock_divider) - phase) >> clock_divider) + event_delay - 1) << clock_divider) + phase;
304 		else
305 			event_time = 0;
306 
307 	} else {
308 		logerror("decrementing counter\n");
309 		exit(1);
310 	}
311 
312 	if(old_event_time != event_time && update_cpu)
313 		cpu->internal_update();
314 }
315 
h8_timer16_device(const machine_config & mconfig,const char * tag,device_t * owner,uint32_t clock)316 h8_timer16_device::h8_timer16_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) :
317 	device_t(mconfig, H8_TIMER16, tag, owner, clock),
318 	cpu(*this, DEVICE_SELF_OWNER)
319 {
320 }
321 
set_info(int count,uint8_t tstr)322 void h8_timer16_device::set_info(int count, uint8_t tstr)
323 {
324 	timer_count = count;
325 	default_tstr = tstr;
326 }
327 
device_start()328 void h8_timer16_device::device_start()
329 {
330 	memset(timer_channel, 0, sizeof(timer_channel));
331 	for(int i=0; i<timer_count; i++) {
332 		char tm[2];
333 		sprintf(tm, "%d", i);
334 		timer_channel[i] = subdevice<h8_timer16_channel_device>(tm);
335 	}
336 
337 	save_item(NAME(tstr));
338 }
339 
device_reset()340 void h8_timer16_device::device_reset()
341 {
342 	tstr = default_tstr;
343 	for(int i=0; i<timer_count; i++)
344 		timer_channel[i]->set_enable((tstr >> i) & 1);
345 }
346 
347 
tstr_r()348 uint8_t h8_timer16_device::tstr_r()
349 {
350 	return tstr;
351 }
352 
tstr_w(uint8_t data)353 void h8_timer16_device::tstr_w(uint8_t data)
354 {
355 	if(V>=1) logerror("tstr_w %02x\n", data);
356 	tstr = data;
357 	for(int i=0; i<timer_count; i++)
358 		timer_channel[i]->set_enable((tstr >> i) & 1);
359 }
360 
tsyr_r()361 uint8_t h8_timer16_device::tsyr_r()
362 {
363 	return 0x00;
364 }
365 
tsyr_w(uint8_t data)366 void h8_timer16_device::tsyr_w(uint8_t data)
367 {
368 	if(V>=1) logerror("tsyr_w %02x\n", data);
369 }
370 
tmdr_r()371 uint8_t h8_timer16_device::tmdr_r()
372 {
373 	return 0x00;
374 }
375 
tmdr_w(uint8_t data)376 void h8_timer16_device::tmdr_w(uint8_t data)
377 {
378 	if(V>=1) logerror("tmdr_w %02x\n", data);
379 }
380 
tfcr_r()381 uint8_t h8_timer16_device::tfcr_r()
382 {
383 	return 0x00;
384 }
385 
tfcr_w(uint8_t data)386 void h8_timer16_device::tfcr_w(uint8_t data)
387 {
388 	if(V>=1) logerror("tfcr_w %02x\n", data);
389 }
390 
toer_r()391 uint8_t h8_timer16_device::toer_r()
392 {
393 	return 0x00;
394 }
395 
toer_w(uint8_t data)396 void h8_timer16_device::toer_w(uint8_t data)
397 {
398 	if(V>=1) logerror("toer_w %02x\n", data);
399 }
400 
tocr_r()401 uint8_t h8_timer16_device::tocr_r()
402 {
403 	return 0x00;
404 }
405 
tocr_w(uint8_t data)406 void h8_timer16_device::tocr_w(uint8_t data)
407 {
408 	if(V>=1) logerror("tocr_w %02x\n", data);
409 }
410 
tisr_r(offs_t offset)411 uint8_t h8_timer16_device::tisr_r(offs_t offset)
412 {
413 	uint8_t r = 0;
414 	for(int i=0; i<timer_count; i++)
415 		r |= timer_channel[i]->tisr_r(offset) << i;
416 	for(int i=timer_count; i<4; i++)
417 		r |= 0x11 <<i;
418 
419 	if(V>=1) logerror("tisr%c_r %02x\n", 'a'+offset, r);
420 
421 	return r;
422 }
423 
tisr_w(offs_t offset,uint8_t data)424 void h8_timer16_device::tisr_w(offs_t offset, uint8_t data)
425 {
426 	if(V>=1) logerror("tisr%c_w %02x\n", 'a'+offset, data);
427 	for(int i=0; i<timer_count; i++)
428 		timer_channel[i]->tisr_w(offset, data >> i);
429 }
430 
tisrc_r()431 uint8_t h8_timer16_device::tisrc_r()
432 {
433 	return tisr_r(2);
434 }
435 
tisrc_w(uint8_t data)436 void h8_timer16_device::tisrc_w(uint8_t data)
437 {
438 	tisr_w(2, data);
439 }
440 
tolr_w(uint8_t data)441 void h8_timer16_device::tolr_w(uint8_t data)
442 {
443 	if(V>=1) logerror("tocr_w %02x\n", data);
444 }
445 
446 
447 
tier_update()448 void h8_timer16_channel_device::tier_update()
449 {
450 }
451 
isr_update(uint8_t val)452 void h8_timer16_channel_device::isr_update(uint8_t val)
453 {
454 }
455 
isr_to_sr() const456 uint8_t h8_timer16_channel_device::isr_to_sr() const
457 {
458 	return 0x00;
459 }
460 
tcr_update()461 void h8_timer16_channel_device::tcr_update()
462 {
463 }
464 
tisr_w(int offset,uint8_t value)465 void h8_timer16_channel_device::tisr_w(int offset, uint8_t value)
466 {
467 	update_counter();
468 	if(!(value & 0x01)) {
469 		switch(offset) {
470 		case 0:
471 			isr &= ~IRQ_A;
472 			break;
473 		case 1:
474 			isr &= ~IRQ_B;
475 			break;
476 		case 2:
477 			isr &= ~IRQ_V;
478 			break;
479 		}
480 	}
481 	if(value & 0x10) {
482 		switch(offset) {
483 		case 0:
484 			ier |= IRQ_A;
485 			break;
486 		case 1:
487 			ier |= IRQ_B;
488 			break;
489 		case 2:
490 			ier |= IRQ_V;
491 			break;
492 		}
493 	} else {
494 		switch(offset) {
495 		case 0:
496 			ier &= ~IRQ_A;
497 			break;
498 		case 1:
499 			ier &= ~IRQ_B;
500 			break;
501 		case 2:
502 			ier &= ~IRQ_V;
503 			break;
504 		}
505 	}
506 	recalc_event();
507 }
508 
tisr_r(int offset) const509 uint8_t h8_timer16_channel_device::tisr_r(int offset) const
510 {
511 	switch(offset) {
512 	case 0:
513 		return ((ier & IRQ_A) ? 0x10 : 0x00) | ((isr & IRQ_A) ? 0x01 : 0x00);
514 	case 1:
515 		return ((ier & IRQ_B) ? 0x10 : 0x00) | ((isr & IRQ_B) ? 0x01 : 0x00);
516 	case 2:
517 		return ((ier & IRQ_V) ? 0x10 : 0x00) | ((isr & IRQ_V) ? 0x01 : 0x00);
518 	}
519 	return 0x00;
520 }
521 
h8h_timer16_channel_device(const machine_config & mconfig,const char * tag,device_t * owner,uint32_t clock)522 h8h_timer16_channel_device::h8h_timer16_channel_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) :
523 	h8_timer16_channel_device(mconfig, H8H_TIMER16_CHANNEL, tag, owner, clock)
524 {
525 }
526 
~h8h_timer16_channel_device()527 h8h_timer16_channel_device::~h8h_timer16_channel_device()
528 {
529 }
530 
set_info(int _tgr_count,int _tbr_count,const char * intc,int irq_base)531 void h8h_timer16_channel_device::set_info(int _tgr_count, int _tbr_count, const char *intc, int irq_base)
532 {
533 	tgr_count = _tgr_count;
534 	tbr_count = _tbr_count;
535 	intc_tag = intc;
536 
537 	interrupt[0] = irq_base++;
538 	interrupt[1] = irq_base++;
539 	interrupt[2] = -1;
540 	interrupt[3] = -1;
541 	interrupt[4] = irq_base;
542 	interrupt[5] = irq_base;
543 }
544 
tier_update()545 void h8h_timer16_channel_device::tier_update()
546 {
547 	tier = tier | 0xf8;
548 	ier =
549 		(tier & 0x01 ? IRQ_A : 0) |
550 		(tier & 0x02 ? IRQ_B : 0) |
551 		(tier & 0x04 ? IRQ_V : 0);
552 }
553 
isr_update(uint8_t val)554 void h8h_timer16_channel_device::isr_update(uint8_t val)
555 {
556 	if(!(val & 1))
557 		isr &= ~IRQ_A;
558 	if(!(val & 2))
559 		isr &= ~IRQ_B;
560 	if(!(val & 4))
561 		isr &= ~IRQ_V;
562 }
563 
isr_to_sr() const564 uint8_t h8h_timer16_channel_device::isr_to_sr() const
565 {
566 	return 0xf8 | (isr & IRQ_V ? 4 : 0) | (isr & IRQ_B ? 2 : 0) | (isr & IRQ_A ? 1 : 0);
567 }
568 
569 
tcr_update()570 void h8h_timer16_channel_device::tcr_update()
571 {
572 	switch(tcr & 0x60) {
573 	case 0x00:
574 		tgr_clearing = TGR_CLEAR_NONE;
575 		if(V>=1) logerror("No automatic tcnt clearing\n");
576 		break;
577 	case 0x20: case 0x40: {
578 		tgr_clearing = tcr & 0x20 ? 0 : 1;
579 		if(V>=1) logerror("Auto-clear on tgr%c (%04x)\n", 'a'+tgr_clearing, tgr[tgr_clearing]);
580 		break;
581 	}
582 	case 0x60:
583 		tgr_clearing = TGR_CLEAR_EXT;
584 		if(V>=1) logerror("External sync clear\n");
585 		break;
586 	}
587 
588 	int count_type = tcr & 7;
589 	if(count_type < 4) {
590 		clock_type = DIV_1;
591 		clock_divider = count_type;
592 		if(V>=1) logerror("clock divider %d (%d)\n", clock_divider, 1 << clock_divider);
593 		if(count_type <= DIV_2)
594 			phase = 0;
595 		else {
596 			switch(tcr & 0x18) {
597 			case 0x00:
598 				phase = 0;
599 				if(V>=1) logerror("Phase 0\n");
600 				break;
601 			case 0x08:
602 				phase = 1 << (clock_divider-1);
603 				if(V>=1) logerror("Phase 180\n");
604 				break;
605 			case 0x10: case 0x18:
606 				phase = 0;
607 				clock_divider--;
608 				if(V>=1) logerror("Phase 0+180\n");
609 				break;
610 			}
611 		}
612 	} else {
613 		clock_type = INPUT_A + (count_type-4);
614 		clock_divider = 0;
615 		phase = 0;
616 		if(V>=1) logerror("counting input %c\n", 'a'+count_type-INPUT_A);
617 	}
618 }
619 
h8s_timer16_channel_device(const machine_config & mconfig,const char * tag,device_t * owner,uint32_t clock)620 h8s_timer16_channel_device::h8s_timer16_channel_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) :
621 	h8_timer16_channel_device(mconfig, H8S_TIMER16_CHANNEL, tag, owner, clock)
622 {
623 }
624 
~h8s_timer16_channel_device()625 h8s_timer16_channel_device::~h8s_timer16_channel_device()
626 {
627 }
628 
set_chain(const char * _chain_tag)629 void h8s_timer16_channel_device::set_chain(const char *_chain_tag)
630 {
631 	chain_tag = _chain_tag;
632 }
633 
set_info(int _tgr_count,uint8_t _tier_mask,const char * intc,int irq_base,int t0,int t1,int t2,int t3,int t4,int t5,int t6,int t7)634 void h8s_timer16_channel_device::set_info(int _tgr_count, uint8_t _tier_mask, const char *intc, int irq_base,
635 											int t0, int t1, int t2, int t3, int t4, int t5, int t6, int t7)
636 {
637 	tgr_count = _tgr_count;
638 	tbr_count = 0;
639 	tier_mask = _tier_mask;
640 	intc_tag = intc;
641 
642 	interrupt[0] = irq_base++;
643 	interrupt[1] = irq_base++;
644 	interrupt[2] = tier_mask & 0x04 ? -1 : irq_base++;
645 	interrupt[3] = tier_mask & 0x08 ? -1 : irq_base++;
646 	interrupt[4] = irq_base;
647 	interrupt[5] = tier_mask & 0x20 ? -1 : irq_base++;
648 
649 	count_types[0] = t0;
650 	count_types[1] = t1;
651 	count_types[2] = t2;
652 	count_types[3] = t3;
653 	count_types[4] = t4;
654 	count_types[5] = t5;
655 	count_types[6] = t6;
656 	count_types[7] = t7;
657 }
658 
tier_update()659 void h8s_timer16_channel_device::tier_update()
660 {
661 	tier = (tier & ~tier_mask) | 0x40;
662 	ier =
663 		(tier & 0x01 ? IRQ_A : 0) |
664 		(tier & 0x02 ? IRQ_B : 0) |
665 		(tier & 0x04 ? IRQ_C : 0) |
666 		(tier & 0x08 ? IRQ_D : 0) |
667 		(tier & 0x10 ? IRQ_V : 0) |
668 		(tier & 0x20 ? IRQ_U : 0) |
669 		(tier & 0x80 ? IRQ_TRIG : 0);
670 }
671 
isr_update(uint8_t val)672 void h8s_timer16_channel_device::isr_update(uint8_t val)
673 {
674 	isr &= (val | tier_mask | 0xc0);
675 }
676 
isr_to_sr() const677 uint8_t h8s_timer16_channel_device::isr_to_sr() const
678 {
679 	return 0xc0 | isr;
680 }
681 
tcr_update()682 void h8s_timer16_channel_device::tcr_update()
683 {
684 	switch(tcr & 0x60) {
685 	case 0x00:
686 		tgr_clearing = TGR_CLEAR_NONE;
687 		if(V>=1) logerror("No automatic tcnt clearing\n");
688 		break;
689 	case 0x20: case 0x40: {
690 		tgr_clearing = tcr & 0x20 ? 0 : 1;
691 		if(tgr_count > 2 && (tcr & 0x80))
692 			tgr_clearing += 2;
693 		if(V>=1) logerror("Auto-clear on tgr%c\n", 'a'+tgr_clearing);
694 		break;
695 	}
696 	case 0x60:
697 		tgr_clearing = TGR_CLEAR_EXT;
698 		if(V>=1) logerror("External sync clear\n");
699 		break;
700 	}
701 
702 	int count_type = count_types[tcr & 7];
703 	if(count_type >= DIV_1 && clock_type <= DIV_4) {
704 		clock_type = DIV_1;
705 		clock_divider = count_type - DIV_1;
706 		if(V>=1) logerror("clock divider %d (%d)\n", clock_divider, 1 << clock_divider);
707 		if(!clock_divider)
708 			phase = 0;
709 		else {
710 			switch(tcr & 0x18) {
711 			case 0x00:
712 				phase = 0;
713 				if(V>=1) logerror("Phase 0\n");
714 				break;
715 			case 0x08:
716 				phase = 1 << (clock_divider-1);
717 				if(V>=1) logerror("Phase 180\n");
718 				break;
719 			case 0x10: case 0x18:
720 				phase = 0;
721 				clock_divider--;
722 				if(V>=1) logerror("Phase 0+180\n");
723 				break;
724 			}
725 		}
726 
727 	} else if(count_type == CHAIN) {
728 		clock_type = CHAIN;
729 		clock_divider = 0;
730 		phase = 0;
731 		if(V>=1) logerror("chained timer\n");
732 
733 	} else if(count_type >= INPUT_A && count_type <= INPUT_D) {
734 		clock_type = count_type;
735 		clock_divider = 0;
736 		phase = 0;
737 		if(V>=1) logerror("counting input %c\n", 'a'+count_type-INPUT_A);
738 	}
739 }
740