1 // license:BSD-3-Clause
2 // copyright-holders:Michael Zapf
3 /****************************************************************************
4 
5     TMS9901 Programmable System Interface
6     See tms9901.c for documentation
7 
8     Raphael Nabet
9     Michael Zapf
10 
11     February 2012: Rewritten as class
12 
13 *****************************************************************************/
14 
15 #ifndef MAME_MACHINE_TMS9901_H
16 #define MAME_MACHINE_TMS9901_H
17 
18 
DECLARE_DEVICE_TYPE(TMS9901,tms9901_device)19 DECLARE_DEVICE_TYPE(TMS9901, tms9901_device)
20 
21 /***************************************************************************
22     MACROS
23 ***************************************************************************/
24 
25 /***************************************************************************
26     CLASS DEFINITION
27 ***************************************************************************/
28 
29 class tms9901_device : public device_t
30 {
31 public:
32 	// I/O pins
33 	enum
34 	{
35 		INT1=1,
36 		INT2,
37 		INT3,
38 		INT4,
39 		INT5,
40 		INT6,
41 		INT7_P15,
42 		INT8_P14,
43 		INT9_P13,
44 		INT10_P12,
45 		INT11_P11,
46 		INT12_P10,
47 		INT13_P9,
48 		INT14_P8,
49 		INT15_P7,
50 		P0,
51 		P1,
52 		P2,
53 		P3,
54 		P4,
55 		P5,
56 		P6
57 	} pins;
58 
59 	tms9901_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
60 
61 	void set_int_line(int pin_number, int state);
62 
63 	void rst1_line(int state);
64 
65 	// Synchronous clock input
66 	void phi_line(int state);
67 
68 	uint8_t read(offs_t offset);
69 	void write(offs_t offset, uint8_t data);
70 
71 	bool read_bit(int bit);
72 	void write_bit(int bit, bool set);
73 
74 	auto p_out_cb(int n) { return m_write_p[n].bind(); }
75 	auto read_cb() { return m_read_port.bind(); }
76 	auto intreq_cb() { return m_interrupt.bind(); }
77 
78 	// Pins IC3...IC0
79 	// When no interrupt is active, the IC lines are all set to 1
80 	// The difference to /INT15 is that INTREQ is cleared.
81 	int get_int_level() { return m_int_pending? m_int_level : 15; }
82 
83 	// Return PIO all outputs; ports configured as inputs return 1
84 	// Used by si5500
85 	uint16_t pio_outputs() const { return m_pio_output | ~m_pio_direction; }
86 
87 	void set_poll_int_lines(bool poll) { m_poll_lines = poll; }
88 
89 private:
90 	static constexpr device_timer_id DECREMENTER = 0;
91 
92 	virtual void device_timer(emu_timer &timer, device_timer_id id, int param, void *ptr) override;
93 	void soft_reset();
94 
95 	void device_start() override;
96 	void device_stop() override;
97 	void device_reset() override;
98 
99 	// Common method for device_reset and rst1_line
100 	void do_reset();
101 
102 	// Common clock handling
103 	void timer_clock_in(line_state clk);
104 
105 	// Direction and value of P pins
106 	bool is_output(int p);
107 	bool output_value(int p);
108 	void set_and_latch_output(int p, bool val);
109 	void set_bit(uint16_t& bitfield, int pos, bool val);
110 
111 	int m_int_level;
112 	int m_last_level;
113 
114 	// State of the INT1-INT15 lines (must be inverted when queried)
115 	// Note that the levels must also be delivered when reading the pins, which
116 	// may require to latch the int levels on the caller's side.
117 	uint16_t m_int_line;
118 	uint16_t m_int_mask;
119 	bool m_int_pending;
120 	bool m_poll_lines;
121 
122 	// Find the interrupt with the lowest level (most important)
123 	void prioritize_interrupts();
124 
125 	// Outgoing INTREQ* line
126 	void signal_int();
127 
128 	// Sample the interrupt inputs.
129 	void sample_interrupt_inputs();
130 
131 	// P15..P0; 1=output H, 0=output L
132 	uint16_t m_pio_output;
133 
134 	// For P15..P0; 1=output, 0=input
135 	// Once set to 1, a reset is necessary to return the pin to input
136 	uint16_t m_pio_direction;
137 
138 	// =======================================================================
139 
140 	// TMS9901 clock mode
141 	// false = interrupt mode (read interrupt state, write interrupt enable mask)
142 	// true = clock mode (read/write clock interval)
143 	bool m_clock_mode;
144 
145 	// Clock divider
146 	int  m_clockdiv;
147 
148 	// Clock has reached 0
149 	bool m_timer_int_pending;
150 
151 	// Timer, used to emulate the decrementer register
152 	emu_timer *m_decrementer;
153 
154 	// Clock interval, loaded in decrementer when it reaches 0.
155 	uint16_t m_clock_register;
156 
157 	// Current decrementer value
158 	uint16_t m_decrementer_value;
159 
160 	// when we go into timer mode, the decrementer is copied there to allow to read it reliably
161 	uint16_t m_clock_read_register;
162 
163 	// =======================================================================
164 
165 	// Read callback.
166 	devcb_read8        m_read_port;
167 
168 	// I/O lines, used for output. When used as inputs, the levels are delivered via the m_read_block
169 	devcb_write_line::array<16> m_write_p;
170 
171 	// INTREQ pin
172 	devcb_write_line   m_interrupt;
173 };
174 
175 #endif // MAME_MACHINE_TMS9901_H
176