1 // license:BSD-3-Clause
2 // copyright-holders:F. Ulivi
3 /*********************************************************************
4 
5     phi.h
6 
7     HP PHI (Processor-to-Hpib-Interface) (1AA6-6x04)
8 
9 *********************************************************************/
10 
11 #ifndef MAME_MACHINE_PHI_H
12 #define MAME_MACHINE_PHI_H
13 
14 
15 class phi_device : public device_t
16 {
17 public:
18 	// construction/destruction
19 	phi_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
20 
21 	// See ieee488.h
22 	enum phi_488_signal_t
23 	{
24 		PHI_488_EOI,
25 		PHI_488_DAV,
26 		PHI_488_NRFD,
27 		PHI_488_NDAC,
28 		PHI_488_IFC,
29 		PHI_488_SRQ,
30 		PHI_488_ATN,
31 		PHI_488_REN,
32 		PHI_488_SIGNAL_COUNT
33 	};
34 
35 	// Set read and write callbacks to access DIO bus on IEEE-488
dio_read_cb()36 	auto dio_read_cb() { return m_dio_read_func.bind(); }
dio_write_cb()37 	auto dio_write_cb() { return m_dio_write_func.bind(); }
38 	// Set write callbacks to access uniline signals on IEEE-488
eoi_write_cb()39 	auto eoi_write_cb() { return m_signal_wr_fns[ PHI_488_EOI ].bind(); }
dav_write_cb()40 	auto dav_write_cb() { return m_signal_wr_fns[ PHI_488_DAV ].bind(); }
nrfd_write_cb()41 	auto nrfd_write_cb() { return m_signal_wr_fns[ PHI_488_NRFD ].bind(); }
ndac_write_cb()42 	auto ndac_write_cb() { return m_signal_wr_fns[ PHI_488_NDAC ].bind(); }
ifc_write_cb()43 	auto ifc_write_cb() { return m_signal_wr_fns[ PHI_488_IFC ].bind(); }
srq_write_cb()44 	auto srq_write_cb() { return m_signal_wr_fns[ PHI_488_SRQ ].bind(); }
atn_write_cb()45 	auto atn_write_cb() { return m_signal_wr_fns[ PHI_488_ATN ].bind(); }
ren_write_cb()46 	auto ren_write_cb() { return m_signal_wr_fns[ PHI_488_REN ].bind(); }
47 	// Set write callback for INT signal
int_write_cb()48 	auto int_write_cb() { return m_int_write_func.bind(); }
49 	// Set write callback for DMARQ signal
dmarq_write_cb()50 	auto dmarq_write_cb() { return m_dmarq_write_func.bind(); }
51 	// Set read callback for SYS_CNTRL signal
sys_cntrl_read_cb()52 	auto sys_cntrl_read_cb() { return m_sys_cntrl_read_func.bind(); }
53 
54 	DECLARE_WRITE_LINE_MEMBER(eoi_w);
55 	DECLARE_WRITE_LINE_MEMBER(dav_w);
56 	DECLARE_WRITE_LINE_MEMBER(nrfd_w);
57 	DECLARE_WRITE_LINE_MEMBER(ndac_w);
58 	DECLARE_WRITE_LINE_MEMBER(ifc_w);
59 	DECLARE_WRITE_LINE_MEMBER(srq_w);
60 	DECLARE_WRITE_LINE_MEMBER(atn_w);
61 	DECLARE_WRITE_LINE_MEMBER(ren_w);
62 
63 	void bus_dio_w(uint8_t data);
64 
65 	void set_ext_signal(phi_488_signal_t signal , int state);
66 
67 	// Register read/write
68 	// Mapping of PHI register bits:
69 	// Reg. bit PHI bit
70 	// =================
71 	// 15       0
72 	// 14       1
73 	// 13       =0=
74 	// 12       =0=
75 	// 11       =0=
76 	// 10       =0=
77 	// 9        =0=
78 	// 8        =0=
79 	// 7        8
80 	// 6        9
81 	// 5        10
82 	// 4        11
83 	// 3        12
84 	// 2        13
85 	// 1        14
86 	// 0        15
87 	void reg16_w(offs_t offset, uint16_t data);
88 	uint16_t reg16_r(offs_t offset);
89 	void reg8_w(offs_t offset, uint8_t data);
90 	uint8_t reg8_r(offs_t offset);
91 
92 protected:
93 	phi_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock);
94 
95 	// device-level overrides
96 	virtual void device_start() override;
97 	virtual void device_reset() override;
98 	virtual void device_timer(emu_timer &timer, device_timer_id id, int param, void *ptr) override;
99 
100 private:
101 	// Depth of inbound/outbound FIFOs
102 	static constexpr unsigned FIFO_SIZE = 8;
103 
104 	devcb_read8 m_dio_read_func;
105 	devcb_write8 m_dio_write_func;
106 	devcb_write_line::array<PHI_488_SIGNAL_COUNT> m_signal_wr_fns;
107 	devcb_write_line m_int_write_func;
108 	devcb_write_line m_dmarq_write_func;
109 	devcb_read_line m_sys_cntrl_read_func;
110 	bool m_int_line;
111 	bool m_dmarq_line;
112 
113 	// Internal copy of bus signals
114 	// These signals have the "right" polarity (i.e. the opposite of bus signals, 1=L)
115 	uint8_t m_dio;
116 	bool m_signals[ PHI_488_SIGNAL_COUNT ];
117 	bool m_ext_signals[ PHI_488_SIGNAL_COUNT ];
118 
119 	bool m_no_recursion;
120 
121 	bool m_sys_controller;
122 	bool m_loopback;
123 	bool m_id_enabled;
124 
125 	// SH (Source Handshake) states
126 	enum {
127 		PHI_SH_SIDS,    // & SIWS
128 		PHI_SH_SGNS,    // & SWNS
129 		PHI_SH_SDYS,
130 		PHI_SH_STRS
131 	};
132 
133 	int m_sh_state;
134 
135 	// AH (Acceptor Handshake) states
136 	enum {
137 		PHI_AH_AIDS,
138 		PHI_AH_ANRS,
139 		PHI_AH_ACRS,
140 		PHI_AH_ACDS,
141 		PHI_AH_ACDS_FROZEN, // Non-standard state: IF CMD rejected because of even parity
142 		PHI_AH_AWNS
143 	};
144 
145 	int m_ah_state;
146 
147 	// T (Talker) states
148 	enum {
149 		PHI_T_TIDS,
150 		PHI_T_TADS,
151 		PHI_T_SPAS,
152 		PHI_T_TACS,
153 		// The following are non-standard states for IDENTIFY sequencing
154 		PHI_T_ID1,  // Addressed by secondary address
155 		PHI_T_ID2,  // Sending 1st byte
156 		PHI_T_ID3,  // Waiting to send 2nd byte
157 		PHI_T_ID4,  // Sending 2nd byte
158 		PHI_T_ID5   // 2nd byte sent, end of sequence
159 	};
160 
161 	int m_t_state;
162 	bool m_t_spms;  // False: SPIS, true: SPMS
163 
164 	// L (Listener) states
165 	enum {
166 		PHI_L_LIDS,
167 		PHI_L_LADS,
168 		PHI_L_LACS
169 	};
170 
171 	int m_l_state;
172 
173 	// SR (Service Request) states
174 	enum {
175 		PHI_SR_NPRS,
176 		PHI_SR_SRQS,
177 		PHI_SR_APRS
178 	};
179 
180 	int m_sr_state;
181 
182 	// RL (Remote Local) states
183 	bool m_rl_rems; // false: LOCS, true: REMS
184 
185 	// PP (Parallel poll) states
186 	enum {
187 		PHI_PP_PPIS,
188 		PHI_PP_PPSS,
189 		PHI_PP_PPAS
190 	};
191 
192 	int m_pp_state;
193 	uint8_t m_ppr_msg;
194 	bool m_s_sense;
195 
196 	// C (Controller) states
197 	enum {
198 		PHI_C_CIDS,
199 		PHI_C_CADS,
200 		PHI_C_CACS,
201 		PHI_C_CPPS,
202 		PHI_C_CSBS,
203 		PHI_C_CSHS,
204 		PHI_C_CAWS,
205 		PHI_C_CTRS,
206 		PHI_C_CSWS
207 	};
208 
209 	int m_c_state;
210 
211 	// Secondary address decoder states
212 	enum {
213 		PHI_SA_NONE,
214 		PHI_SA_PACS,
215 		PHI_SA_TPAS,
216 		PHI_SA_LPAS,
217 		PHI_SA_UNT
218 	};
219 
220 	int m_sa_state;
221 
222 	uint8_t m_be_counter;
223 	uint16_t m_reg_status;
224 	uint16_t m_reg_int_cond;
225 	uint16_t m_reg_int_mask;
226 	uint16_t m_reg_1st_id;
227 	uint16_t m_reg_2nd_id;
228 	uint16_t m_reg_control;
229 	uint16_t m_reg_address;
230 	util::fifo<uint16_t , FIFO_SIZE> m_fifo_in;
231 	util::fifo<uint16_t , FIFO_SIZE> m_fifo_out;
232 
233 	typedef enum {
234 		NBA_NONE,
235 		NBA_CMD_FROM_OFIFO,
236 		NBA_BYTE_FROM_OFIFO,
237 		NBA_FROM_SPAS,
238 		NBA_FROM_ID2,
239 		NBA_FROM_ID4
240 	} nba_origin_t;
241 
242 	int m_nba_origin;
243 
244 	// Timers
245 	emu_timer *m_sh_dly_timer;
246 	emu_timer *m_c_dly_timer;
247 
248 	void int_reg_w(offs_t offset , uint16_t data);
249 
250 	uint8_t get_dio(void);
251 	void set_dio(uint8_t data);
252 	bool get_signal(phi_488_signal_t signal);
253 	void set_signal(phi_488_signal_t signal , bool state);
254 
255 	void pon_msg(void);
256 	void update_488(void);
257 	void update_fsm(void);
258 	nba_origin_t nba_msg(uint8_t& new_byte , bool& new_eoi) const;
259 	void clear_nba(nba_origin_t origin);
260 	bool if_cmd_received(uint8_t byte);
261 	bool byte_received(uint8_t byte , bool eoi);
262 	void rx_n_data_freeze(uint16_t word);
263 	bool ton_msg(void) const;
264 	bool lon_msg(void) const;
265 	bool odd_parity(uint8_t byte) const;
266 	uint8_t my_address(void) const;
267 	bool tcs_msg(void) const;
268 	bool rpp_msg(void) const;
269 	uint8_t get_pp_response();
270 	bool controller_in_charge(void) const;
271 	void configure_pp_response();
272 	void update_pp();
273 	void update_interrupt();
274 	void update_dmarq();
275 };
276 
277 // device type definition
278 DECLARE_DEVICE_TYPE(PHI, phi_device)
279 
280 #endif // MAME_MACHINE_PHI_H
281