summaryrefslogtreecommitdiffstatshomepage
path: root/src/devices/machine/phi.h
blob: 5e9eb0782e348d8d9821cd22cd347595051ee589 (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
// license:BSD-3-Clause
// copyright-holders:F. Ulivi
/*********************************************************************

    phi.h

    HP PHI (Processor-to-Hpib-Interface) (1AA6-6x04)

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

#ifndef MAME_MACHINE_PHI_H
#define MAME_MACHINE_PHI_H


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

	// See ieee488.h
	enum phi_488_signal_t
	{
		PHI_488_EOI,
		PHI_488_DAV,
		PHI_488_NRFD,
		PHI_488_NDAC,
		PHI_488_IFC,
		PHI_488_SRQ,
		PHI_488_ATN,
		PHI_488_REN,
		PHI_488_SIGNAL_COUNT
	};

	// Set read and write callbacks to access DIO bus on IEEE-488
	auto dio_read_cb() { return m_dio_read_func.bind(); }
	auto dio_write_cb() { return m_dio_write_func.bind(); }
	// Set write callbacks to access uniline signals on IEEE-488
	auto eoi_write_cb() { return m_signal_wr_fns[ PHI_488_EOI ].bind(); }
	auto dav_write_cb() { return m_signal_wr_fns[ PHI_488_DAV ].bind(); }
	auto nrfd_write_cb() { return m_signal_wr_fns[ PHI_488_NRFD ].bind(); }
	auto ndac_write_cb() { return m_signal_wr_fns[ PHI_488_NDAC ].bind(); }
	auto ifc_write_cb() { return m_signal_wr_fns[ PHI_488_IFC ].bind(); }
	auto srq_write_cb() { return m_signal_wr_fns[ PHI_488_SRQ ].bind(); }
	auto atn_write_cb() { return m_signal_wr_fns[ PHI_488_ATN ].bind(); }
	auto ren_write_cb() { return m_signal_wr_fns[ PHI_488_REN ].bind(); }
	// Set write callback for INT signal
	auto int_write_cb() { return m_int_write_func.bind(); }
	// Set write callback for DMARQ signal
	auto dmarq_write_cb() { return m_dmarq_write_func.bind(); }
	// Set read callback for SYS_CNTRL signal
	auto sys_cntrl_read_cb() { return m_sys_cntrl_read_func.bind(); }

	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(bus_dio_w);

	void set_ext_signal(phi_488_signal_t signal , int state);

	// Register read/write
	// Mapping of PHI register bits:
	// Reg. bit PHI bit
	// =================
	// 15       0
	// 14       1
	// 13       =0=
	// 12       =0=
	// 11       =0=
	// 10       =0=
	// 9        =0=
	// 8        =0=
	// 7        8
	// 6        9
	// 5        10
	// 4        11
	// 3        12
	// 2        13
	// 1        14
	// 0        15
	DECLARE_WRITE16_MEMBER(reg16_w);
	DECLARE_READ16_MEMBER(reg16_r);
	DECLARE_WRITE8_MEMBER(reg8_w);
	DECLARE_READ8_MEMBER(reg8_r);

protected:
	phi_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock);

	// 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;

private:
	// Depth of inbound/outbound FIFOs
	static constexpr unsigned FIFO_SIZE = 8;

	devcb_read8 m_dio_read_func;
	devcb_write8 m_dio_write_func;
	devcb_write_line m_signal_wr_fns[ PHI_488_SIGNAL_COUNT ];
	devcb_write_line m_int_write_func;
	devcb_write_line m_dmarq_write_func;
	devcb_read_line m_sys_cntrl_read_func;
	bool m_int_line;
	bool m_dmarq_line;

	// Internal copy of bus signals
	// These signals have the "right" polarity (i.e. the opposite of bus signals, 1=L)
	uint8_t m_dio;
	bool m_signals[ PHI_488_SIGNAL_COUNT ];
	bool m_ext_signals[ PHI_488_SIGNAL_COUNT ];

	bool m_no_recursion;

	bool m_sys_controller;
	bool m_loopback;
	bool m_id_enabled;

	// SH (Source Handshake) states
	enum {
		PHI_SH_SIDS,    // & SIWS
		PHI_SH_SGNS,    // & SWNS
		PHI_SH_SDYS,
		PHI_SH_STRS
	};

	int m_sh_state;

	// AH (Acceptor Handshake) states
	enum {
		PHI_AH_AIDS,
		PHI_AH_ANRS,
		PHI_AH_ACRS,
		PHI_AH_ACDS,
		PHI_AH_ACDS_FROZEN, // Non-standard state: IF CMD rejected because of even parity
		PHI_AH_AWNS
	};

	int m_ah_state;

	// T (Talker) states
	enum {
		PHI_T_TIDS,
		PHI_T_TADS,
		PHI_T_SPAS,
		PHI_T_TACS,
		// The following are non-standard states for IDENTIFY sequencing
		PHI_T_ID1,  // Addressed by secondary address
		PHI_T_ID2,  // Sending 1st byte
		PHI_T_ID3,  // Waiting to send 2nd byte
		PHI_T_ID4,  // Sending 2nd byte
		PHI_T_ID5   // 2nd byte sent, end of sequence
	};

	int m_t_state;
	bool m_t_spms;  // False: SPIS, true: SPMS

	// L (Listener) states
	enum {
		PHI_L_LIDS,
		PHI_L_LADS,
		PHI_L_LACS
	};

	int m_l_state;

	// SR (Service Request) states
	enum {
		PHI_SR_NPRS,
		PHI_SR_SRQS,
		PHI_SR_APRS
	};

	int m_sr_state;

	// RL (Remote Local) states
	bool m_rl_rems; // false: LOCS, true: REMS

	// PP (Parallel poll) states
	enum {
		PHI_PP_PPIS,
		PHI_PP_PPSS,
		PHI_PP_PPAS
	};

	int m_pp_state;
	uint8_t m_ppr_msg;
	bool m_s_sense;

	// C (Controller) states
	enum {
		PHI_C_CIDS,
		PHI_C_CADS,
		PHI_C_CACS,
		PHI_C_CPPS,
		PHI_C_CSBS,
		PHI_C_CSHS,
		PHI_C_CAWS,
		PHI_C_CTRS,
		PHI_C_CSWS
	};

	int m_c_state;

	// Secondary address decoder states
	enum {
		PHI_SA_NONE,
		PHI_SA_PACS,
		PHI_SA_TPAS,
		PHI_SA_LPAS,
		PHI_SA_UNT
	};

	int m_sa_state;

	uint8_t m_be_counter;
	uint16_t m_reg_status;
	uint16_t m_reg_int_cond;
	uint16_t m_reg_int_mask;
	uint16_t m_reg_1st_id;
	uint16_t m_reg_2nd_id;
	uint16_t m_reg_control;
	uint16_t m_reg_address;
	util::fifo<uint16_t , FIFO_SIZE> m_fifo_in;
	util::fifo<uint16_t , FIFO_SIZE> m_fifo_out;

	typedef enum {
		NBA_NONE,
		NBA_CMD_FROM_OFIFO,
		NBA_BYTE_FROM_OFIFO,
		NBA_FROM_SPAS,
		NBA_FROM_ID2,
		NBA_FROM_ID4
	} nba_origin_t;

	int m_nba_origin;

	// Timers
	emu_timer *m_sh_dly_timer;
	emu_timer *m_c_dly_timer;

	void int_reg_w(offs_t offset , uint16_t data);

	uint8_t get_dio(void);
	void set_dio(uint8_t data);
	bool get_signal(phi_488_signal_t signal);
	void set_signal(phi_488_signal_t signal , bool state);

	void pon_msg(void);
	void update_488(void);
	void update_fsm(void);
	nba_origin_t nba_msg(uint8_t& new_byte , bool& new_eoi) const;
	void clear_nba(nba_origin_t origin);
	bool if_cmd_received(uint8_t byte);
	bool byte_received(uint8_t byte , bool eoi);
	void rx_n_data_freeze(uint16_t word);
	bool ton_msg(void) const;
	bool lon_msg(void) const;
	bool odd_parity(uint8_t byte) const;
	uint8_t my_address(void) const;
	bool tcs_msg(void) const;
	bool rpp_msg(void) const;
	uint8_t get_pp_response();
	bool controller_in_charge(void) const;
	void configure_pp_response();
	void update_pp();
	void update_interrupt();
	void update_dmarq();
};

// device type definition
DECLARE_DEVICE_TYPE(PHI, phi_device)

#endif // MAME_MACHINE_PHI_H