summaryrefslogtreecommitdiffstatshomepage
path: root/src/devices/machine/tms9914.h
blob: 2c21b1a4d4bed4727ab640cb621bab3274dc13ed (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
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
// license:BSD-3-Clause
// copyright-holders:F. Ulivi
/*********************************************************************

    tms9914.h

    Texas Instruments TMS9914(A) GPIB Controller

                            _____   _____
                ACCRQ/   1 |*    \_/     | 40  Vcc
                ACCGR/   2 |             | 39  TR
                   CE/   3 |             | 38  DIO1
                   WE/   4 |             | 37  DIO2
                  DBIN   5 |             | 36  DIO3
                   RS0   6 |             | 35  DIO4
                   RS1   7 |             | 34  DIO5
                   RS2   8 |             | 33  DIO6
                  INT/   9 |             | 32  DIO7
                    D7  10 |  TMS9914    | 31  DIO8
                    D6  11 |  TMS9914A   | 30  CONT/
                    D5  12 |             | 29  SRQ
                    D4  13 |             | 28  ATN
                    D3  14 |             | 27  EOI
                    D2  15 |             | 26  DAV
                    D1  16 |             | 25  NRFD
                    D0  17 |             | 24  NDAC
                    O/  18 |             | 23  IFC
                RESET/  19 |             | 22  REN
                   Vss  20 |_____________| 21  TE

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

#ifndef MAME_MACHINE_TMS9914_H
#define MAME_MACHINE_TMS9914_H

#pragma once

// Set read and write callbacks to access DIO bus on IEEE-488
#define MCFG_TMS9914_DIO_READWRITE_CB(_read , _write)                   \
	downcast<tms9914_device &>(*device).set_dio_read_cb(DEVCB_##_read); \
	downcast<tms9914_device &>(*device).set_dio_write_cb(DEVCB_##_write);

// Set write callbacks to access uniline signals on IEEE-488
#define MCFG_TMS9914_EOI_WRITE_CB(_write)                               \
	downcast<tms9914_device &>(*device).set_488_signal_write_cb(tms9914_device::IEEE_488_EOI , DEVCB_##_write);

#define MCFG_TMS9914_DAV_WRITE_CB(_write)                               \
	downcast<tms9914_device &>(*device).set_488_signal_write_cb(tms9914_device::IEEE_488_DAV , DEVCB_##_write);

#define MCFG_TMS9914_NRFD_WRITE_CB(_write)                              \
	downcast<tms9914_device &>(*device).set_488_signal_write_cb(tms9914_device::IEEE_488_NRFD , DEVCB_##_write);

#define MCFG_TMS9914_NDAC_WRITE_CB(_write)                              \
	downcast<tms9914_device &>(*device).set_488_signal_write_cb(tms9914_device::IEEE_488_NDAC , DEVCB_##_write);

#define MCFG_TMS9914_IFC_WRITE_CB(_write)                               \
	downcast<tms9914_device &>(*device).set_488_signal_write_cb(tms9914_device::IEEE_488_IFC , DEVCB_##_write);

#define MCFG_TMS9914_SRQ_WRITE_CB(_write)                               \
	downcast<tms9914_device &>(*device).set_488_signal_write_cb(tms9914_device::IEEE_488_SRQ , DEVCB_##_write);

#define MCFG_TMS9914_ATN_WRITE_CB(_write)                               \
	downcast<tms9914_device &>(*device).set_488_signal_write_cb(tms9914_device::IEEE_488_ATN , DEVCB_##_write);

#define MCFG_TMS9914_REN_WRITE_CB(_write)                               \
	downcast<tms9914_device &>(*device).set_488_signal_write_cb(tms9914_device::IEEE_488_REN , DEVCB_##_write);

// Set write callback for INT signal
#define MCFG_TMS9914_INT_WRITE_CB(_write)                               \
	downcast<tms9914_device &>(*device).set_int_write_cb(DEVCB_##_write);

// Set write callback for ACCRQ signal
#define MCFG_TMS9914_ACCRQ_WRITE_CB(_write)                               \
	downcast<tms9914_device &>(*device).set_accrq_write_cb(DEVCB_##_write);

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

	// See ieee488.h
	enum ieee_488_signal_t {
		IEEE_488_EOI,
		IEEE_488_DAV,
		IEEE_488_NRFD,
		IEEE_488_NDAC,
		IEEE_488_IFC,
		IEEE_488_SRQ,
		IEEE_488_ATN,
		IEEE_488_REN,
		IEEE_488_SIGNAL_COUNT
	};

	template <class Object> devcb_base& set_dio_read_cb(Object &&cb)
	{ return m_dio_read_func.set_callback(std::forward<Object>(cb)); }

	template <class Object> devcb_base& set_dio_write_cb(Object &&cb)
	{ return m_dio_write_func.set_callback(std::forward<Object>(cb)); }

	template <class Object> devcb_base& set_488_signal_write_cb(ieee_488_signal_t signal , Object &&cb)
	{ return m_signal_wr_fns[ signal ].set_callback(std::forward<Object>(cb)); }

	template <class Object> devcb_base& set_int_write_cb(Object &&cb)
	{ return m_int_write_func.set_callback(std::forward<Object>(cb)); }

	template <class Object> devcb_base& set_accrq_write_cb(Object &&cb)
	{ return m_accrq_write_func.set_callback(std::forward<Object>(cb)); }

	DECLARE_WRITE_LINE_MEMBER(eoi_w);
	DECLARE_WRITE_LINE_MEMBER(dav_w);
	DECLARE_WRITE_LINE_MEMBER(nrfd_w);
	DECLARE_WRITE_LINE_MEMBER(ndac_w);
	DECLARE_WRITE_LINE_MEMBER(ifc_w);
	DECLARE_WRITE_LINE_MEMBER(srq_w);
	DECLARE_WRITE_LINE_MEMBER(atn_w);
	DECLARE_WRITE_LINE_MEMBER(ren_w);

	DECLARE_WRITE8_MEMBER(reg8_w);
	DECLARE_READ8_MEMBER(reg8_r);

	// CONT output: true when 9914 is current controller-in-charge
	DECLARE_READ_LINE_MEMBER(cont_r);

private:
	// device-level overrides
	virtual void device_start() override;
	virtual void device_reset() override;
	virtual void device_timer(emu_timer &timer, device_timer_id id, int param, void *ptr) override;

	devcb_read8 m_dio_read_func;
	devcb_write8 m_dio_write_func;
	devcb_write_line m_signal_wr_fns[ IEEE_488_SIGNAL_COUNT ];
	devcb_write_line m_int_write_func;
	devcb_write_line m_accrq_write_func;
	bool m_int_line;
	bool m_accrq_line;

	uint8_t m_dio;
	bool m_signals[ IEEE_488_SIGNAL_COUNT ];
	bool m_ext_signals[ IEEE_488_SIGNAL_COUNT ];
	bool m_no_reflection;
	bool m_ext_state_change;

	// Registers
	uint8_t m_reg_int0_status;
	uint8_t m_reg_int0_mask;
	uint8_t m_reg_int1_status;
	uint8_t m_reg_int1_mask;
	uint8_t m_reg_address;
	uint8_t m_reg_serial_p;
	uint8_t m_reg_parallel_p;
	uint8_t m_reg_2nd_parallel_p;
	uint8_t m_reg_di;
	uint8_t m_reg_do;
	bool m_reg_ulpa;

	// Auxiliary cmd states
	bool m_swrst;
	bool m_hdfa;
	bool m_hdfe;
	bool m_rtl;
	bool m_gts;
	bool m_rpp;
	bool m_sic;
	bool m_sre;
	bool m_dai;
	bool m_pts;
	bool m_stdl;
	bool m_shdw;
	bool m_vstdl;

	// AH (Acceptor Handshake) states
	enum {
		FSM_AH_AIDS,
		FSM_AH_ANRS,
		FSM_AH_ACRS,
		FSM_AH_ACDS1,
		FSM_AH_ACDS2,
		FSM_AH_AWNS
	};

	int m_ah_state;
	bool m_ah_adhs;
	bool m_ah_anhs;
	bool m_ah_aehs;

	// SH (Source Handshake) states
	enum {
		FSM_SH_SIDS,
		FSM_SH_SGNS,
		FSM_SH_SDYS,
		FSM_SH_SERS,
		FSM_SH_STRS
	};

	int m_sh_state;
	bool m_sh_shfs;
	bool m_sh_vsts;

	// T (Talker) states
	enum {
		FSM_T_TIDS,
		FSM_T_TADS,
		FSM_T_TACS,
		FSM_T_SPAS
	};

	int m_t_state;
	bool m_t_tpas;
	bool m_t_spms;

	// Talker EOI generator states
	enum {
		FSM_T_ENIS,
		FSM_T_ENRS,
		FSM_T_ERAS,
		FSM_T_ENAS
	};

	int m_t_eoi_state;

	// L (Listener) states
	enum {
		FSM_L_LIDS,
		FSM_L_LADS,
		FSM_L_LACS
	};

	int m_l_state;
	bool m_l_lpas;

	// SR (Service request) states
	enum {
		FSM_SR_NPRS,
		FSM_SR_SRQS,
		FSM_SR_APRS1,
		FSM_SR_APRS2
	};

	int m_sr_state;

	// RL (Remote Local) states
	enum {
		FSM_RL_LOCS,
		FSM_RL_REMS,
		FSM_RL_RWLS,
		FSM_RL_LWLS
	};

	int m_rl_state;

	// PP (Parallel poll) states
	bool m_pp_ppas;

	// C (Controller) states
	enum {
		FSM_C_CIDS,
		FSM_C_CADS,
		FSM_C_CACS,
		FSM_C_CSBS,
		FSM_C_CWAS,
		FSM_C_CSHS,
		FSM_C_CSWS,
		FSM_C_CAWS,
		FSM_C_CPWS
	};

	int m_c_state;

	// Timers
	enum {
		SH_DELAY_TMR_ID,
		AH_DELAY_TMR_ID,
		C_DELAY_TMR_ID
	};

	emu_timer *m_sh_dly_timer;
	emu_timer *m_ah_dly_timer;
	emu_timer *m_c_dly_timer;

	uint8_t get_dio();
	void set_dio(uint8_t data);
	bool get_signal(ieee_488_signal_t signal) const;
	bool get_ifcin() const;
	void set_ext_signal(ieee_488_signal_t signal , int state);
	void set_signal(ieee_488_signal_t signal , bool state);
	void do_swrst();
	bool listener_reset() const;
	bool talker_reset() const;
	bool controller_reset() const;
	bool sh_active() const;
	void update_fsm();
	bool is_my_address(uint8_t addr);
	void do_LAF();
	void do_TAF();
	void if_cmd_received(uint8_t if_cmd);
	void dab_received(uint8_t dab , bool eoi);
	void do_aux_cmd(unsigned cmd , bool set_bit);
	void set_int0_bit(unsigned bit_no);
	void set_int1_bit(unsigned bit_no);
	void update_int();
	void update_ifc();
	void update_ren();
	void set_accrq(bool state);
};

// device type definition
DECLARE_DEVICE_TYPE(TMS9914, tms9914_device)

#endif // MAME_MACHINE_TMS9914_H