summaryrefslogtreecommitdiffstatshomepage
path: root/src/devices/machine/z80ctc.h
blob: 98dd852ddd2e4743c1dbe6930e7807a824b0ea99 (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
133
// license:BSD-3-Clause
// copyright-holders:Wilbert Pol
/***************************************************************************

    Z80 CTC (Z8430) implementation

****************************************************************************
                            _____   _____
                    D4   1 |*    \_/     | 28  D3
                    D5   2 |             | 27  D2
                    D6   3 |             | 26  D1
                    D7   4 |             | 25  D0
                   GND   5 |             | 24  +5V
                   _RD   6 |             | 23  CLK/TRG0
                ZC/TOO   7 |   Z80-CTC   | 22  CLK/TRG1
                ZC/TO1   8 |             | 21  CLK/TRG2
                ZC/TO2   9 |             | 20  CLK/TRG3
                 _IORQ  10 |             | 19  CS1
                   IEO  11 |             | 18  CS0
                  _INT  12 |             | 17  _RESET
                   IEI  13 |             | 16  _CE
                   _M1  14 |_____________| 15  CLK

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

#ifndef MAME_MACHINE_Z80CTC_H
#define MAME_MACHINE_Z80CTC_H

#pragma once

#include "machine/z80daisy.h"


//**************************************************************************
//  TYPE DEFINITIONS
//**************************************************************************

// forward declaration
class z80ctc_device;

// ======================> z80ctc_channel_device

// a single channel within the CTC
class z80ctc_channel_device : public device_t
{
	friend class z80ctc_device;

public:
	// construction/destruction
	z80ctc_channel_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock = 0);

protected:
	// device-level overrides
	virtual void device_start() override;
	virtual void device_reset() override;

	u8 read();
	void write(u8 data);

	attotime period() const;
	void trigger(bool state);
	TIMER_CALLBACK_MEMBER(timer_callback);

	required_device<z80ctc_device> m_device; // pointer back to our device
	int             m_index;                // our channel index
	u16             m_mode;                 // current mode
	u16             m_tconst;               // time constant
	u16             m_down;                 // down counter (clock mode only)
	bool            m_extclk;               // current signal from the external clock
	emu_timer *     m_timer;                // array of active timers
	u8              m_int_state;            // interrupt status (for daisy chain)
};

// ======================> z80ctc_device

class z80ctc_device :   public device_t,
						public device_z80daisy_interface
{
	friend class z80ctc_channel_device;

public:
	// construction/destruction
	z80ctc_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock);

	auto intr_callback() { return m_intr_cb.bind(); }
	template <int Channel> auto zc_callback() { return m_zc_cb[Channel].bind(); } // m_zc_cb[3] not supported on a standard ctc, only used for the tmpz84c015
	template <int Channel> void set_clk(u32 clock) { channel_config(Channel).set_clock(clock); }
	template <int Channel> void set_clk(const XTAL &xtal) { channel_config(Channel).set_clock(xtal); }

	// read/write handlers
	uint8_t read(offs_t offset);
	void write(offs_t offset, uint8_t data);
	DECLARE_WRITE_LINE_MEMBER( trg0 );
	DECLARE_WRITE_LINE_MEMBER( trg1 );
	DECLARE_WRITE_LINE_MEMBER( trg2 );
	DECLARE_WRITE_LINE_MEMBER( trg3 );

	u16 get_channel_constant(int ch) const { return m_channel[ch]->m_tconst; }

protected:
	// device-level overrides
	virtual void device_add_mconfig(machine_config &config) override;
	virtual void device_resolve_objects() override;
	virtual void device_start() override;
	virtual void device_reset_after_children() override;

	// z80daisy_interface overrides
	virtual int z80daisy_irq_state() override;
	virtual int z80daisy_irq_ack() override;
	virtual void z80daisy_irq_reti() override;

private:
	// internal helpers
	void interrupt_check();

	z80ctc_channel_device &channel_config(int ch) { return *subdevice<z80ctc_channel_device>(m_channel[ch].finder_tag()); }

	// internal state
	devcb_write_line   m_intr_cb;              // interrupt callback
	devcb_write_line   m_zc_cb[4];             // zero crossing/timer output callbacks

	u8                 m_vector;               // interrupt vector

	// subdevice for each channel
	required_device_array<z80ctc_channel_device, 4> m_channel;
};


// device type definitions
DECLARE_DEVICE_TYPE(Z80CTC, z80ctc_device)
DECLARE_DEVICE_TYPE(Z80CTC_CHANNEL, z80ctc_channel_device)

#endif // MAME_MACHINE_Z80CTC_H