summaryrefslogtreecommitdiffstatshomepage
path: root/src/devices/cpu/h8/h8_timer8.h
blob: 9ed4a06d6e4e8d3b1c2173c634b874583bc783f5 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
// license:BSD-3-Clause
// copyright-holders:Olivier Galibert
/***************************************************************************

    h8_timer8.h

    H8 8 bits timer

***************************************************************************/

#ifndef MAME_CPU_H8_H8_TIMER8_H
#define MAME_CPU_H8_H8_TIMER8_H

#pragma once

#include "h8.h"
#include "h8_intc.h"

class h8_timer8_channel_device : public device_t {
public:
	enum {
		STOPPED,
		CHAIN_A,
		CHAIN_OVERFLOW,
		INPUT_UP,
		INPUT_DOWN,
		INPUT_UPDOWN,
		DIV
	};

	h8_timer8_channel_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock);
	template<typename T, typename U> h8_timer8_channel_device(const machine_config &mconfig, const char *tag, device_t *owner, T &&cpu, U &&intc, int irq_ca, int irq_cb, int irq_v,
				int div1, int div2, int div3, int div4, int div5, int div6)
		: h8_timer8_channel_device(mconfig, tag, owner, 0)
	{
		m_cpu.set_tag(std::forward<T>(cpu));
		m_intc.set_tag(std::forward<U>(intc));
		m_irq_ca = irq_ca;
		m_irq_cb = irq_cb;
		m_irq_v = irq_v;
		m_div_tab[0] = div1;
		m_div_tab[1] = div2;
		m_div_tab[2] = div3;
		m_div_tab[3] = div4;
		m_div_tab[4] = div5;
		m_div_tab[5] = div6;
	}

	u8 tcr_r();
	void tcr_w(u8 data);
	u8 tcsr_r();
	void tcsr_w(u8 data);
	u8 tcor_r(offs_t offset);
	void tcor_w(offs_t offset, u8 data);
	u8 tcnt_r();
	void tcnt_w(u8 data);

	u64 internal_update(u64 current_time);
	void notify_standby(int state);
	void set_extra_clock_bit(bool bit);

	void chained_timer_overflow();
	void chained_timer_tcora();

protected:
	enum {
		TCR_CKS   = 0x07,
		TCR_CCLR  = 0x18,
		TCR_OVIE  = 0x20,
		TCR_CMIEA = 0x40,
		TCR_CMIEB = 0x80,

		TCSR_OS   = 0x0f,
		TCSR_ADTE = 0x10,
		TCSR_OVF  = 0x20,
		TCSR_CMFA = 0x40,
		TCSR_CMFB = 0x80
	};

	enum {
		CLEAR_NONE,
		CLEAR_A,
		CLEAR_B,
		CLEAR_EXTERNAL
	};

	required_device<h8_device> m_cpu;
	required_device<h8_intc_device> m_intc;
	optional_device<h8_timer8_channel_device> m_chained_timer;

	int m_irq_ca, m_irq_cb, m_irq_v, m_chain_type;
	int m_div_tab[6];
	u8 m_tcor[2];
	u8 m_tcr, m_tcsr, m_tcnt;
	bool m_extra_clock_bit, m_has_adte, m_has_ice;
	int m_clock_type, m_clock_divider, m_clear_type, m_counter_cycle;
	u64 m_last_clock_update, m_event_time;

	h8_timer8_channel_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, u32 clock);

	virtual void device_start() override ATTR_COLD;
	virtual void device_reset() override ATTR_COLD;

	void update_counter(u64 cur_time = 0, u64 delta = 0);
	void recalc_event(u64 cur_time = 0);

	void update_tcr();
};

class h8h_timer8_channel_device : public h8_timer8_channel_device {
public:
	h8h_timer8_channel_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock);
	template<typename T, typename U, typename V> h8h_timer8_channel_device(const machine_config &mconfig, const char *tag, device_t *owner, T &&cpu, U &&intc, int irq_ca, int irq_cb, int irq_v,
				V &&chain, int chain_type, bool has_adte, bool has_ice)
		: h8h_timer8_channel_device(mconfig, tag, owner, 0)
	{
		m_cpu.set_tag(std::forward<T>(cpu));
		m_intc.set_tag(std::forward<U>(intc));
		m_irq_ca = irq_ca;
		m_irq_cb = irq_cb;
		m_irq_v = irq_v;
		m_chained_timer.set_tag(std::forward<V>(chain));
		m_chain_type = chain_type;
		m_has_adte = has_adte;
		m_has_ice = has_ice;
	}
};

DECLARE_DEVICE_TYPE(H8_TIMER8_CHANNEL,  h8_timer8_channel_device)
DECLARE_DEVICE_TYPE(H8H_TIMER8_CHANNEL, h8h_timer8_channel_device)

#endif // MAME_CPU_H8_H8_TIMER8_H