summaryrefslogtreecommitdiffstatshomepage
path: root/src/devices/machine/6840ptm.h
blob: 614901625a4177cd75e6e9a5ed13f22c1e4600a6 (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
134
135
136
137
138
139
// license:BSD-3-Clause
// copyright-holders:James Wallace
/***************************************************************************

    Motorola 6840 (PTM)

    Programmable Timer Module

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

#ifndef MAME_MACHINE_6840PTM_H
#define MAME_MACHINE_6840PTM_H

#pragma once


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

// ======================> ptm6840_device

class ptm6840_device :  public device_t
{
public:
	// construction/destruction
	ptm6840_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);

	void set_external_clocks(double clock0, double clock1, double clock2) { m_external_clock[0] = clock0; m_external_clock[1] = clock1; m_external_clock[2] = clock2; }
	void set_external_clocks(const XTAL &clock0, const XTAL &clock1, const XTAL &clock2) { set_external_clocks(clock0.dvalue(), clock1.dvalue(), clock2.dvalue()); }
	auto o1_callback() { return m_out_cb[0].bind(); }
	auto o2_callback() { return m_out_cb[1].bind(); }
	auto o3_callback() { return m_out_cb[2].bind(); }
	auto irq_callback() { return m_irq_cb.bind(); }

	int status(int idx) const { return m_enabled[idx]; }            // get whether timer is enabled
	int irq_state() const { return m_irq; }                         // get IRQ state
	int count(int idx) const { return compute_counter(idx); }       // get counter value
	void set_ext_clock(int counter, double clock);                  // set clock frequency
	int ext_clock(int idx) const { return m_external_clock[idx]; }  // get clock frequency

	void write(offs_t offset, uint8_t data);
	uint8_t read(offs_t offset);

	void set_gate(int idx, int state);
	DECLARE_WRITE_LINE_MEMBER( set_g1 ) { set_gate(0, state); }
	DECLARE_WRITE_LINE_MEMBER( set_g2 ) { set_gate(1, state); }
	DECLARE_WRITE_LINE_MEMBER( set_g3 ) { set_gate(2, state); }

	void set_clock(int idx, int state);
	DECLARE_WRITE_LINE_MEMBER( set_c1 ) { set_clock(0, state); }
	DECLARE_WRITE_LINE_MEMBER( set_c2 ) { set_clock(1, state); }
	DECLARE_WRITE_LINE_MEMBER( set_c3 ) { set_clock(2, state); }

	void update_interrupts();

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

private:
	void deduct_from_counter(int idx);
	void tick(int counter);
	TIMER_CALLBACK_MEMBER(state_changed);

	int compute_counter(int idx) const;
	void reload_counter(int idx);
	void update_expiration_for_clock_source(int idx, bool changed_to_external = false, double new_external_clock = 0.0);

	enum
	{
		PTM_6840_CTRL1   = 0,
		PTM_6840_CTRL2   = 1,
		PTM_6840_STATUS  = 1,
		PTM_6840_MSBBUF1 = 2,
		PTM_6840_LSB1    = 3,
		PTM_6840_MSBBUF2 = 4,
		PTM_6840_LSB2    = 5,
		PTM_6840_MSBBUF3 = 6,
		PTM_6840_LSB3    = 7
	};

	enum
	{
		RESET_TIMERS    = 0x01,
		CR1_SELECT      = 0x01,
		T3_PRESCALE_EN  = 0x01,
		INTERNAL_CLK_EN = 0x02,
		COUNT_MODE_8BIT = 0x04,
		MODE_BITS       = 0x38,
		INTERRUPT_EN    = 0x40,
		COUNT_OUT_EN    = 0x80
	};

	enum
	{
		TIMER1_IRQ  = 0x01,
		TIMER2_IRQ  = 0x02,
		TIMER3_IRQ  = 0x04,
		ANY_IRQ     = 0x80
	};

	double m_external_clock[3];

	devcb_write_line::array<3> m_out_cb;
	devcb_write_line m_irq_cb;

	uint8_t m_control_reg[3];
	bool m_output[3]; // Output states
	bool m_gate[3];   // Counter gate states
	bool m_clk[3];    // Clock states
	bool m_enabled[3];
	uint8_t m_mode[3];
	bool m_single_fired[3];
	uint8_t m_t3_divisor;
	uint8_t m_t3_scaler;
	uint8_t m_irq;
	uint8_t m_status_reg;
	uint8_t m_status_read_since_int;
	uint8_t m_lsb_buffer;
	uint8_t m_msb_buffer;

	// Each PTM has 3 timers
	emu_timer *m_timer[3];

	uint16_t m_latch[3];
	uint16_t m_counter[3];
	attotime m_disable_time[3];

	static const char *const opmode[];
};


// device type definition
DECLARE_DEVICE_TYPE(PTM6840, ptm6840_device)

#endif // MAME_MACHINE_6840PTM_H