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 PHI supports these features of HP-IB:
10 * SH1
11 * AH1
12 * T1/TE1
13 * L1/LE1
14 * SR1
15 * RL2
16 * PP1
17 * DC1
18 * DT1
19 * C1,C2,C3,C4,C5
20 * HP non-standard IDENTIFY sequence
21
22 Fun fact: PHI has no clock input, its FSMs are driven only by
23 changes in input signals and by a few internal monostables
24
25 Main reference for this ASIC:
26 HP 12009-90001, sep 82, HP12009A HP-IB Interface Reference Manual
27
28 *********************************************************************/
29
30 #include "emu.h"
31 #include "phi.h"
32
33 // Debugging
34 #include "logmacro.h"
35 #define LOG_NOISY_MASK (LOG_GENERAL << 1)
36 #define LOG_NOISY(...) LOGMASKED(LOG_NOISY_MASK, __VA_ARGS__)
37 #define LOG_REG_MASK (LOG_NOISY_MASK << 1)
38 #define LOG_REG(...) LOGMASKED(LOG_REG_MASK, __VA_ARGS__)
39 #define LOG_INT_MASK (LOG_REG_MASK << 1)
40 #define LOG_INT(...) LOGMASKED(LOG_INT_MASK, __VA_ARGS__)
41 #undef VERBOSE
42 #define VERBOSE LOG_GENERAL
43
44 // Bit manipulation
45 namespace {
BIT_MASK(unsigned n)46 template<typename T> constexpr T BIT_MASK(unsigned n)
47 {
48 return (T)1U << n;
49 }
50
BIT_CLR(T & w,unsigned n)51 template<typename T> void BIT_CLR(T& w , unsigned n)
52 {
53 w &= ~BIT_MASK<T>(n);
54 }
55
BIT_SET(T & w,unsigned n)56 template<typename T> void BIT_SET(T& w , unsigned n)
57 {
58 w |= BIT_MASK<T>(n);
59 }
60 }
61
62 // Timers
63 enum {
64 SH_DELAY_TMR_ID,
65 C_DELAY_TMR_ID
66 };
67
68 // Register addresses
69 enum {
70 REG_R_INT_COND = 0, // R 0: Interrupting conditions
71 REG_W_INT_COND = 0, // W 0: Interrupting conditions
72 REG_R_INT_MASK = 1, // R 1: Interrupt mask
73 REG_W_INT_MASK = 1, // W 1: Interrupt mask
74 REG_R_INBOUND_FIFO = 2, // R 2: Inbound FIFO
75 REG_W_OUTBOUND_FIFO = 2,// W 2: Outbound FIFO
76 REG_R_STATUS = 3, // R 3: Status
77 REG_W_STATUS = 3, // W 3: Status
78 REG_R_CONTROL = 4, // R 4: Control
79 REG_W_CONTROL = 4, // W 4: Control
80 REG_R_ADDRESS = 5, // R 5: HPIB address
81 REG_W_ADDRESS = 5, // W 5: HPIB address
82 REG_R_1ST_ID = 6, // R 6: 1st ID byte
83 REG_W_1ST_ID = 6, // W 6: 1st ID byte
84 REG_R_2ND_ID = 7, // R 7: 2nd ID byte
85 REG_W_2ND_ID = 7 // W 7: 2nd ID byte
86 };
87
88 // All valid bits in registers
89 constexpr uint16_t REG_ALL_MASK = 0xc0ff;
90
91 // D0 & D1 bits
92 constexpr uint16_t REG_D0D1_MASK = 0xc000; // Mask of D0/D1 bits
93 constexpr unsigned REG_D0D1_SHIFT = 14; // Position of D0/D1 bits
94
95 // D8-D15 bits
96 constexpr uint16_t REG_D08D15_MASK = 0xff; // Mask of D8:D15 bits
97
98 // Bits in INT_COND & INT_MASK
99 constexpr unsigned REG_INT_DEV_CLEAR_BIT = 0; // Device clear
100 constexpr unsigned REG_INT_FIFO_IDLE_BIT = 1; // FIFO idle
101 constexpr unsigned REG_INT_FIFO_AV_BIT = 2; // FIFO bytes available
102 constexpr unsigned REG_INT_FIFO_ROOM_BIT = 3; // FIFO room available
103 constexpr unsigned REG_INT_SRQ_BIT = 4; // Service request
104 constexpr unsigned REG_INT_PP_RESPONSE_BIT = 5; // PP response
105 constexpr unsigned REG_INT_PROC_ABORT_BIT = 6; // Processor handshake abort
106 constexpr unsigned REG_INT_STATUS_CH_BIT = 7; // Status change
107 constexpr unsigned REG_INT_PARITY_ERR_BIT = 14; // Parity error
108 constexpr unsigned REG_INT_PENDING_BIT = 15; // Interrupt pending
109 constexpr uint16_t REG_INT_CLEARABLE_MASK = 0x40c1; // Mask of clearable bits
110 constexpr uint16_t REG_INT_STATE_MASK = 0x803e; // Mask of "state" bits
111
112 // Bits in inbound FIFO
113 //constexpr uint16_t REG_IFIFO_NORMAL_MASK = 0x0000; // Mask of D0/D1 bits for "normal" bytes
114 constexpr uint16_t REG_IFIFO_CNT_EXP_MASK = 0x8000; // Mask for a byte that caused byte count to expire
115 constexpr uint16_t REG_IFIFO_LAST_MASK = 0xc000; // Mask for last byte in a record
116 constexpr uint16_t REG_IFIFO_2_ADDR_MASK = 0x4000; // Mask for secondary addresses
117 constexpr unsigned REG_IFIFO_TALK_BIT = 5; // Bit of "talk" flag
118
119 // Bits in outbound FIFO
120 constexpr unsigned REG_OFIFO_SPECIAL_BIT = 14; // Bit to discriminate between normal bytes and the rest
121 constexpr unsigned REG_OFIFO_END_BIT = 15; // Bit of EOI
122 constexpr uint16_t REG_OFIFO_IFCMD_MASK = 0x4000; // Mask of interface commands
123 constexpr uint16_t REG_OFIFO_UNCNT_MASK = 0xc000; // Mask of uncounted transfer enable
124 constexpr unsigned REG_OFIFO_LF_INH_BIT = 15; // Bit of LF detection inhibit
125
126 // Bits in status register
127 constexpr unsigned REG_STATUS_DATA_FREEZE_BIT = 0; // Outbound data freeze
128 constexpr unsigned REG_STATUS_LISTEN_BIT = 1; // Addressed to listen
129 constexpr unsigned REG_STATUS_TALK_BIT = 2; // Addressed to talk or identify
130 constexpr unsigned REG_STATUS_SYS_CTRL_BIT = 3; // System controller
131 constexpr unsigned REG_STATUS_CONTROLLER_BIT = 4; // Current controller
132 constexpr unsigned REG_STATUS_REMOTE_BIT = 5; // Remote state
133 constexpr unsigned REG_STATUS_D0D1_BIT = 6; // D0/D1 bit access
134 constexpr uint16_t REG_STATUS_STATE_MASK = 0x3e; // Mask of "state" bits
135
136 // Bits in control register
137 constexpr unsigned REG_CTRL_INIT_OFIFO_BIT = 0; // Initialize outbound FIFO
138 constexpr unsigned REG_CTRL_DMA_FIFO_BIT = 1; // DMA FIFO selection
139 constexpr unsigned REG_CTRL_SERVICE_REQ_BIT = 2; // Request service
140 constexpr unsigned REG_CTRL_PP_RESPONSE_BIT = 3; // Respond to PP
141 constexpr unsigned REG_CTRL_IFC_BIT = 4; // IFC value
142 constexpr unsigned REG_CTRL_REN_BIT = 5; // REN value
143 constexpr unsigned REG_CTRL_PAR_FREEZE_BIT = 6; // Parity freeze
144 constexpr unsigned REG_CTRL_8BIT_PROC_BIT = 7; // 8-bit processor
145
146 // Bits in address register
147 constexpr unsigned REG_ADDR_HPIB_ADDR_BIT = 0; // HPIB address LSB
148 constexpr unsigned REG_ADDR_LA_BIT = 5; // Listen always
149 constexpr unsigned REG_ADDR_TA_BIT = 6; // Talk always
150 constexpr unsigned REG_ADDR_ONLINE_BIT = 7; // Online
151
152 // Interface commands
153 constexpr uint8_t IFCMD_MASK = 0x7f; // Mask of interface commands
154 constexpr uint8_t IFCMD_DCL = 0x14; // Device clear
155 constexpr uint8_t IFCMD_GET = 0x08; // Group execute trigger
156 constexpr uint8_t IFCMD_GTL = 0x01; // Go to local
157 constexpr uint8_t IFCMD_LLO = 0x11; // Local lock-out
158 constexpr uint8_t IFCMD_AG_MASK = 0x60; // Mask of bits identifying address group commands
159 constexpr uint8_t IFCMD_ADDR_MASK = 0x1f; // Mask of address in AG commands
160 constexpr uint8_t IFCMD_LAG_VALUE = 0x20; // Value of LAG commands
161 constexpr uint8_t IFCMD_TAG_VALUE = 0x40; // Value of TAG commands
162 constexpr uint8_t IFCMD_SCG_VALUE = 0x60; // Value of SCG commands
163 constexpr uint8_t IFCMD_PPC = 0x05; // Parallel poll configure
164 constexpr uint8_t IFCMD_PPX_MASK = 0x70; // Mask of PPE/PPD commands
165 constexpr uint8_t IFCMD_PPE_VALUE = 0x60; // Parallel poll enable
166 constexpr unsigned IFCMD_PPE_S_BIT = 3; // Position of "S" bit in PPE
167 constexpr uint8_t IFCMD_PPE_PPR_MASK = 7; // Mask in PPE of PPR msg no.
168 constexpr uint8_t IFCMD_PPD_VALUE = 0x70; // Parallel poll disable
169 constexpr uint8_t IFCMD_PPU = 0x15; // Parallel poll unconfigure
170 constexpr uint8_t IFCMD_SDC = 0x04; // Selected device clear
171 constexpr uint8_t IFCMD_SPD = 0x19; // Serial poll disable
172 constexpr uint8_t IFCMD_SPE = 0x18; // Serial poll enable
173 constexpr uint8_t IFCMD_TCT = 0x09; // Take control
174 constexpr uint8_t IFCMD_UNL = 0x3f; // Unlisten
175 constexpr uint8_t IFCMD_UNT = 0x5f; // Untalk
176
177 // Delays
178 constexpr unsigned DELAY_T1 = 2000; // T1: 2 us
179 constexpr unsigned DELAY_T7 = 500; // T7: 0.5 us
180 constexpr unsigned DELAY_T9 = 1500; // T9: 1.5 us
181 constexpr unsigned DELAY_T10 = 1500; // T10: 1.5 us
182
183 // Controller address
184 constexpr uint8_t CONTROLLER_ADDR = 0x1e; // PHI always has this address when it's a system controller
185
186 // Device type definition
187 DEFINE_DEVICE_TYPE(PHI, phi_device, "hp_phi", "HP Processor-to-HPIB Interface")
188
189 // Constructors
phi_device(const machine_config & mconfig,device_type type,const char * tag,device_t * owner,uint32_t clock)190 phi_device::phi_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock)
191 : device_t(mconfig, type, tag, owner, clock),
192 m_dio_read_func(*this),
193 m_dio_write_func(*this),
194 m_signal_wr_fns(*this),
195 m_int_write_func(*this),
196 m_dmarq_write_func(*this),
197 m_sys_cntrl_read_func(*this)
198 {
199 }
200
phi_device(const machine_config & mconfig,const char * tag,device_t * owner,uint32_t clock)201 phi_device::phi_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
202 : phi_device(mconfig, PHI, tag, owner, clock)
203 {
204 }
205
WRITE_LINE_MEMBER(phi_device::eoi_w)206 WRITE_LINE_MEMBER(phi_device::eoi_w)
207 {
208 set_ext_signal(PHI_488_EOI , state);
209 }
210
WRITE_LINE_MEMBER(phi_device::dav_w)211 WRITE_LINE_MEMBER(phi_device::dav_w)
212 {
213 set_ext_signal(PHI_488_DAV , state);
214 }
215
WRITE_LINE_MEMBER(phi_device::nrfd_w)216 WRITE_LINE_MEMBER(phi_device::nrfd_w)
217 {
218 set_ext_signal(PHI_488_NRFD , state);
219 }
220
WRITE_LINE_MEMBER(phi_device::ndac_w)221 WRITE_LINE_MEMBER(phi_device::ndac_w)
222 {
223 set_ext_signal(PHI_488_NDAC , state);
224 }
225
WRITE_LINE_MEMBER(phi_device::ifc_w)226 WRITE_LINE_MEMBER(phi_device::ifc_w)
227 {
228 set_ext_signal(PHI_488_IFC , state);
229 }
230
WRITE_LINE_MEMBER(phi_device::srq_w)231 WRITE_LINE_MEMBER(phi_device::srq_w)
232 {
233 set_ext_signal(PHI_488_SRQ , state);
234 }
235
WRITE_LINE_MEMBER(phi_device::atn_w)236 WRITE_LINE_MEMBER(phi_device::atn_w)
237 {
238 set_ext_signal(PHI_488_ATN , state);
239 }
240
WRITE_LINE_MEMBER(phi_device::ren_w)241 WRITE_LINE_MEMBER(phi_device::ren_w)
242 {
243 set_ext_signal(PHI_488_REN , state);
244 }
245
bus_dio_w(uint8_t data)246 void phi_device::bus_dio_w(uint8_t data)
247 {
248 update_pp();
249 }
250
set_ext_signal(phi_488_signal_t signal,int state)251 void phi_device::set_ext_signal(phi_488_signal_t signal , int state)
252 {
253 state = !state;
254 if (m_ext_signals[ signal ] != state) {
255 m_ext_signals[ signal ] = state;
256 LOG_NOISY("EXT EOI %d DAV %d NRFD %d NDAC %d IFC %d SRQ %d ATN %d REN %d\n" ,
257 m_ext_signals[ PHI_488_EOI ] ,
258 m_ext_signals[ PHI_488_DAV ] ,
259 m_ext_signals[ PHI_488_NRFD ] ,
260 m_ext_signals[ PHI_488_NDAC ] ,
261 m_ext_signals[ PHI_488_IFC ] ,
262 m_ext_signals[ PHI_488_SRQ ] ,
263 m_ext_signals[ PHI_488_ATN ] ,
264 m_ext_signals[ PHI_488_REN ]);
265 update_fsm();
266 }
267 }
268
reg16_w(offs_t offset,uint16_t data)269 void phi_device::reg16_w(offs_t offset, uint16_t data)
270 {
271 int_reg_w(offset , data & REG_ALL_MASK);
272 }
273
reg16_r(offs_t offset)274 uint16_t phi_device::reg16_r(offs_t offset)
275 {
276 uint16_t res;
277
278 switch (offset) {
279 case REG_R_INT_COND:
280 res = m_reg_int_cond & m_reg_int_mask;
281 break;
282
283 case REG_R_INT_MASK:
284 res = m_reg_int_mask;
285 break;
286
287 case REG_R_INBOUND_FIFO:
288 if (m_fifo_in.empty()) {
289 if (m_c_state == PHI_C_CPPS) {
290 res = get_pp_response();
291 } else {
292 BIT_SET(m_reg_int_cond, REG_INT_PROC_ABORT_BIT);
293 res = 0;
294 }
295 } else {
296 res = m_fifo_in.dequeue();
297 }
298 update_fsm();
299 break;
300
301 case REG_R_STATUS:
302 res = m_reg_status;
303 break;
304
305 case REG_R_CONTROL:
306 res = m_reg_control;
307 break;
308
309 case REG_R_ADDRESS:
310 res = m_reg_address;
311 break;
312
313 case REG_R_1ST_ID:
314 res = m_reg_1st_id;
315 break;
316
317 case REG_R_2ND_ID:
318 res = m_reg_2nd_id;
319 break;
320
321 default:
322 res = 0;
323 LOG("Reading from unmapped address (%u)\n", offset);
324 break;
325 };
326
327 if (offset != REG_R_STATUS) {
328 // Store D0/D1 in top bits of status register
329 m_reg_status = (m_reg_status & ~(3U << REG_STATUS_D0D1_BIT)) |
330 ((res & REG_D0D1_MASK) >> (REG_D0D1_SHIFT - REG_STATUS_D0D1_BIT));
331 }
332
333 LOG_REG("R %u=%04x\n" , offset , res);
334 return res;
335 }
336
reg8_w(offs_t offset,uint8_t data)337 void phi_device::reg8_w(offs_t offset, uint8_t data)
338 {
339 int_reg_w(offset , data);
340 }
341
reg8_r(offs_t offset)342 uint8_t phi_device::reg8_r(offs_t offset)
343 {
344 return (uint8_t)reg16_r(offset);
345 }
346
device_start()347 void phi_device::device_start()
348 {
349 save_item(NAME(m_dio));
350 save_item(NAME(m_signals));
351 save_item(NAME(m_ext_signals));
352 save_item(NAME(m_sys_controller));
353 save_item(NAME(m_loopback));
354 save_item(NAME(m_id_enabled));
355 save_item(NAME(m_sh_state));
356 save_item(NAME(m_ah_state));
357 save_item(NAME(m_t_state));
358 save_item(NAME(m_t_spms));
359 save_item(NAME(m_l_state));
360 save_item(NAME(m_sr_state));
361 save_item(NAME(m_rl_rems));
362 save_item(NAME(m_pp_state));
363 save_item(NAME(m_ppr_msg));
364 save_item(NAME(m_s_sense));
365 save_item(NAME(m_c_state));
366 save_item(NAME(m_sa_state));
367 save_item(NAME(m_be_counter));
368 save_item(NAME(m_reg_status));
369 save_item(NAME(m_reg_int_cond));
370 save_item(NAME(m_reg_int_mask));
371 save_item(NAME(m_reg_1st_id));
372 save_item(NAME(m_reg_2nd_id));
373 save_item(NAME(m_reg_control));
374 save_item(NAME(m_reg_address));
375 save_item(NAME(m_nba_origin));
376
377 m_dio_read_func.resolve_safe(0xff);
378 m_dio_write_func.resolve_safe();
379 m_signal_wr_fns.resolve_all_safe();
380 m_int_write_func.resolve_safe();
381 m_dmarq_write_func.resolve_safe();
382 m_sys_cntrl_read_func.resolve_safe(0);
383
384 m_sh_dly_timer = timer_alloc(SH_DELAY_TMR_ID);
385 m_c_dly_timer = timer_alloc(C_DELAY_TMR_ID);
386 }
387
device_reset()388 void phi_device::device_reset()
389 {
390 m_dio = 0;
391 for (auto& s : m_signals) {
392 s = false;
393 }
394 for (auto& s : m_ext_signals) {
395 s = false;
396 }
397 m_no_recursion = false;
398 // The following variables are set "true" because m_reg_address is set to 0
399 m_sys_controller = true;
400 m_loopback = true;
401 m_id_enabled = false;
402 m_reg_status = 0;
403 m_reg_int_cond = 0;
404 m_reg_int_mask = 0;
405 m_reg_1st_id = 0;
406 m_reg_2nd_id = 0;
407 m_reg_control = 0;
408 m_reg_address = 0;
409 m_fifo_in.clear();
410 m_fifo_out.clear();
411 m_int_line = false;
412 m_int_write_func(false);
413 m_dmarq_line = false;
414 m_dmarq_write_func(false);
415
416 pon_msg();
417 update_488();
418 }
419
device_timer(emu_timer & timer,device_timer_id id,int param,void * ptr)420 void phi_device::device_timer(emu_timer &timer, device_timer_id id, int param, void *ptr)
421 {
422 LOG_NOISY("tmr %d enabled %d\n" , id , timer.enabled());
423 update_fsm();
424 }
425
int_reg_w(offs_t offset,uint16_t data)426 void phi_device::int_reg_w(offs_t offset , uint16_t data)
427 {
428 if (BIT(m_reg_control , REG_CTRL_8BIT_PROC_BIT)) {
429 // In 8-bit mode, D0/D1 come from status register
430 data = (data & REG_D08D15_MASK) | ((m_reg_status << (REG_D0D1_SHIFT - REG_STATUS_D0D1_BIT)) & REG_D0D1_MASK);
431 }
432
433 LOG_REG("W %u=%04x\n" , offset , data);
434
435 switch (offset) {
436 case REG_W_INT_COND:
437 // Bits D1/D8/D9/D15 only are clearable when written to 1
438 m_reg_int_cond &= ~(data & REG_INT_CLEARABLE_MASK);
439 update_fsm();
440 break;
441
442 case REG_W_INT_MASK:
443 m_reg_int_mask = data;
444 update_fsm();
445 break;
446
447 case REG_W_OUTBOUND_FIFO:
448 if (m_fifo_out.full()) {
449 BIT_SET(m_reg_int_cond, REG_INT_PROC_ABORT_BIT);
450 } else {
451 m_fifo_out.enqueue(data);
452 }
453 update_fsm();
454 break;
455
456 case REG_W_STATUS:
457 // Copy D0/D1 access bits into status register
458 m_reg_status = (m_reg_status & ~(3U << REG_STATUS_D0D1_BIT)) |
459 (data & (3U << REG_STATUS_D0D1_BIT));
460 if (BIT(data , REG_STATUS_DATA_FREEZE_BIT) && m_fifo_in.empty()) {
461 BIT_CLR(m_reg_status, REG_STATUS_DATA_FREEZE_BIT);
462 }
463 update_fsm();
464 break;
465
466 case REG_W_CONTROL:
467 // D0/D1/D15 are not mapped into register
468 m_reg_control = data & 0xfe;
469 if (BIT(data , REG_CTRL_INIT_OFIFO_BIT)) {
470 m_fifo_out.clear();
471 if (m_c_state == PHI_C_CSBS) {
472 // Take control asynchronously
473 m_c_state = PHI_C_CSWS;
474 m_c_dly_timer->adjust(attotime::from_nsec(DELAY_T7));
475 }
476 }
477 if (m_loopback) {
478 // TODO: better?
479 m_id_enabled = BIT(m_reg_control , REG_CTRL_PP_RESPONSE_BIT);
480 }
481 update_fsm();
482 break;
483
484 case REG_W_ADDRESS:
485 {
486 // No D0/D1 in register
487 data &= REG_D08D15_MASK;
488 bool prev_ol = BIT(m_reg_address , REG_ADDR_ONLINE_BIT);
489 m_reg_address = data;
490 bool current_ol = BIT(m_reg_address , REG_ADDR_ONLINE_BIT);
491 m_sys_controller = !current_ol || m_sys_cntrl_read_func();
492 m_loopback = !current_ol;
493 if (!current_ol) {
494 // IDENTIFY is enabled by PP_RESPONSE bit in control register
495 m_id_enabled = BIT(m_reg_control , REG_CTRL_PP_RESPONSE_BIT);
496 } else if (!prev_ol) {
497 // Going on-line
498 pon_msg();
499 m_id_enabled = BIT(m_reg_control , REG_CTRL_PP_RESPONSE_BIT);
500 }
501 configure_pp_response();
502 if (prev_ol != current_ol) {
503 update_488();
504 }
505 update_fsm();
506 }
507 break;
508
509 case REG_W_1ST_ID:
510 // No D0/D1 in register
511 m_reg_1st_id = data & REG_D08D15_MASK;
512 update_fsm();
513 break;
514
515 case REG_W_2ND_ID:
516 // No D0/D1 in register
517 m_reg_2nd_id = data & REG_D08D15_MASK;
518 update_fsm();
519 break;
520
521 default:
522 LOG("Writing to unmapped address (%u)\n", offset);
523 break;
524 }
525 }
526
get_dio(void)527 uint8_t phi_device::get_dio(void)
528 {
529 if (m_loopback) {
530 return m_dio;
531 } else {
532 return ~m_dio_read_func();
533 }
534 }
535
set_dio(uint8_t data)536 void phi_device::set_dio(uint8_t data)
537 {
538 if (data != m_dio) {
539 LOG_NOISY("DIO=%02x\n" , data);
540 m_dio = data;
541 if (!m_loopback) {
542 m_dio_write_func(~data);
543 }
544 }
545 }
546
get_signal(phi_488_signal_t signal)547 bool phi_device::get_signal(phi_488_signal_t signal)
548 {
549 if (m_loopback) {
550 return m_signals[ signal ];
551 } else {
552 return m_ext_signals[ signal ];
553 }
554 }
555
set_signal(phi_488_signal_t signal,bool state)556 void phi_device::set_signal(phi_488_signal_t signal , bool state)
557 {
558 if (state != m_signals[ signal ]) {
559 m_signals[ signal ] = state;
560 LOG_NOISY("INT EOI %d DAV %d NRFD %d NDAC %d IFC %d SRQ %d ATN %d REN %d\n" ,
561 m_signals[ PHI_488_EOI ] ,
562 m_signals[ PHI_488_DAV ] ,
563 m_signals[ PHI_488_NRFD ] ,
564 m_signals[ PHI_488_NDAC ] ,
565 m_signals[ PHI_488_IFC ] ,
566 m_signals[ PHI_488_SRQ ] ,
567 m_signals[ PHI_488_ATN ] ,
568 m_signals[ PHI_488_REN ]);
569 if (!m_loopback) {
570 m_signal_wr_fns[ signal ](!state);
571 }
572 }
573 }
574
pon_msg(void)575 void phi_device::pon_msg(void)
576 {
577 m_sh_state = PHI_SH_SIDS;
578 m_ah_state = PHI_AH_AIDS;
579 m_t_state = PHI_T_TIDS;
580 m_t_spms = false;
581 m_l_state = PHI_L_LIDS;
582 m_sr_state = PHI_SR_NPRS;
583 m_rl_rems = false;
584 m_pp_state = PHI_PP_PPIS;
585 m_c_state = PHI_C_CIDS;
586 m_sa_state = PHI_SA_NONE;
587 m_be_counter = 0;
588 m_nba_origin = NBA_NONE;
589 }
590
update_488(void)591 void phi_device::update_488(void)
592 {
593 if (m_loopback) {
594 m_dio_write_func(~0);
595 for (auto& f : m_signal_wr_fns) {
596 f(1);
597 }
598 } else {
599 m_dio_write_func(~m_dio);
600 for (unsigned i = 0; i < PHI_488_SIGNAL_COUNT; i++) {
601 m_signal_wr_fns[ i ](!m_signals[ i ]);
602 }
603 }
604 }
605
update_fsm(void)606 void phi_device::update_fsm(void)
607 {
608 if (m_no_recursion) {
609 // Prevent recursion into this function whenever a signal change propagates through
610 // set_ext_signal
611 return;
612 }
613 m_no_recursion = true;
614
615 set_signal(PHI_488_IFC , m_sys_controller && BIT(m_reg_control , REG_CTRL_IFC_BIT));
616 set_signal(PHI_488_REN , m_sys_controller && BIT(m_reg_control , REG_CTRL_REN_BIT));
617
618 // TODO: improve (see SR FSM)
619 // This is not entirely correct but it works for now (on HP64K, the only system
620 // where it's relevant)
621 set_signal(PHI_488_SRQ , BIT(m_reg_control , REG_CTRL_SERVICE_REQ_BIT));
622
623 bool changed = true;
624 int prev_state;
625 uint8_t new_byte = 0;
626 bool new_eoi = false;
627 bool prev_cic = controller_in_charge();
628 // TODO: SR FSM
629 // Loop until all changes settle
630 while (changed) {
631 LOG_NOISY("SH %d AH %d T %d SPMS %d L %d SR %d PP %d PPR %u S %d C %d SA %d\n" ,
632 m_sh_state , m_ah_state , m_t_state , m_t_spms , m_l_state , m_sr_state ,
633 m_pp_state , m_ppr_msg , m_s_sense , m_c_state , m_sa_state);
634 LOG_NOISY("O E/F=%d/%d I E/F=%d/%d\n" , m_fifo_out.empty() , m_fifo_out.full() , m_fifo_in.empty() , m_fifo_in.full());
635 changed = false;
636
637 // SH FSM
638 prev_state = m_sh_state;
639 bool sh_reset =
640 (get_signal(PHI_488_ATN) && !(m_c_state == PHI_C_CACS || m_c_state == PHI_C_CTRS)) ||
641 (!get_signal(PHI_488_ATN) && !(m_t_state == PHI_T_TACS || m_t_state == PHI_T_SPAS || m_t_state == PHI_T_ID2 || m_t_state == PHI_T_ID4));
642
643 if (sh_reset) {
644 m_sh_state = PHI_SH_SIDS;
645 m_sh_dly_timer->reset();
646 } else {
647 switch (m_sh_state) {
648 case PHI_SH_SIDS:
649 if (m_t_state == PHI_T_TACS ||
650 m_t_state == PHI_T_SPAS ||
651 m_t_state == PHI_T_ID2 ||
652 m_t_state == PHI_T_ID4 ||
653 m_c_state == PHI_C_CACS) {
654 m_sh_state = PHI_SH_SGNS;
655 }
656 break;
657
658 case PHI_SH_SGNS:
659 if ((m_nba_origin = nba_msg(new_byte , new_eoi)) != NBA_NONE) {
660 m_sh_state = PHI_SH_SDYS;
661 m_sh_dly_timer->adjust(attotime::from_nsec(DELAY_T1));
662 LOG_NOISY("SH DLY enabled %d\n" , m_sh_dly_timer->enabled());
663 }
664 break;
665
666 case PHI_SH_SDYS:
667 if (!get_signal(PHI_488_NRFD) && !m_sh_dly_timer->enabled()) {
668 m_sh_state = PHI_SH_STRS;
669 }
670 break;
671
672 case PHI_SH_STRS:
673 if (!get_signal(PHI_488_NDAC)) {
674 LOG("%.6f TX %02x/%d\n" , machine().time().as_double() , m_dio , m_signals[ PHI_488_EOI ]);
675 m_sh_state = PHI_SH_SGNS;
676 clear_nba((nba_origin_t)m_nba_origin);
677 }
678 break;
679
680 default:
681 logerror("Invalid SH state %d\n" , m_sh_state);
682 m_sh_state = PHI_SH_SIDS;
683 }
684 }
685 if (m_sh_state != prev_state) {
686 changed = true;
687 }
688
689 // SH outputs
690 // EOI is controlled by SH & C FSMs
691 bool eoi_signal = false;
692 uint8_t dio_byte = 0;
693 set_signal(PHI_488_DAV , m_sh_state == PHI_SH_STRS);
694 if (m_sh_state == PHI_SH_SDYS || m_sh_state == PHI_SH_STRS) {
695 nba_msg(new_byte , new_eoi);
696 dio_byte = new_byte;
697 eoi_signal = new_eoi;
698 }
699
700 // AH FSM
701 prev_state = m_ah_state;
702 bool ah_reset = !(get_signal(PHI_488_ATN) || m_l_state == PHI_L_LADS || m_l_state == PHI_L_LACS || m_c_state == PHI_C_CSBS);
703 if (ah_reset) {
704 m_ah_state = PHI_AH_AIDS;
705 } else {
706 switch (m_ah_state) {
707 case PHI_AH_AIDS:
708 m_ah_state = PHI_AH_ANRS;
709 break;
710
711 case PHI_AH_ANRS:
712 //if (!tcs_msg() && (get_signal(PHI_488_ATN) || rdy_msg())) {
713 // According to standard either ATN or rdy should also be true, but rdy is always true in PHI
714 if (!tcs_msg()) {
715 m_ah_state = PHI_AH_ACRS;
716 }
717 break;
718
719 case PHI_AH_ACRS:
720 if (get_signal(PHI_488_DAV)) {
721 m_ah_state = PHI_AH_ACDS;
722 }
723 // rdy is always true
724 // } else if (!get_signal(PHI_488_ATN) && !rdy_msg()) {
725 // m_ah_state = PHI_AH_ANRS;
726 // }
727 break;
728
729 case PHI_AH_ACDS:
730 // FSM stays in this state until the acceptor has
731 // accepted the data byte or the interface command.
732 if (get_signal(PHI_488_ATN)) {
733 uint8_t if_cmd = get_dio();
734 bool parity_ok = odd_parity(if_cmd);
735 if (!parity_ok) {
736 BIT_SET(m_reg_int_cond , REG_INT_PARITY_ERR_BIT);
737 }
738 if (BIT(m_reg_control , REG_CTRL_PAR_FREEZE_BIT) && !parity_ok) {
739 // With even parity and PARITY FREEZE set, command is ignored and
740 // AH FSM freezes in ACDS
741 m_ah_state = PHI_AH_ACDS_FROZEN;
742 } else {
743 // Clear parity bit & process command
744 if_cmd &= IFCMD_MASK;
745 if (if_cmd_received(if_cmd)) {
746 m_ah_state = PHI_AH_AWNS;
747 }
748 }
749 } else if (byte_received(get_dio() , get_signal(PHI_488_EOI))) {
750 m_ah_state = PHI_AH_AWNS;
751 }
752 break;
753
754 case PHI_AH_ACDS_FROZEN:
755 case PHI_AH_AWNS:
756 if (!get_signal(PHI_488_DAV)) {
757 m_ah_state = PHI_AH_ANRS;
758 }
759 break;
760
761 default:
762 logerror("Invalid AH state %d\n" , m_ah_state);
763 m_ah_state = PHI_AH_AIDS;
764 }
765 }
766 if (m_ah_state != prev_state) {
767 changed = true;
768 }
769 // AH outputs
770 set_signal(PHI_488_NRFD , m_ah_state == PHI_AH_ANRS || m_ah_state == PHI_AH_ACDS || m_ah_state == PHI_AH_ACDS_FROZEN || m_ah_state == PHI_AH_AWNS);
771 set_signal(PHI_488_NDAC , m_ah_state == PHI_AH_ANRS || m_ah_state == PHI_AH_ACRS || m_ah_state == PHI_AH_ACDS || m_ah_state == PHI_AH_ACDS_FROZEN);
772
773 // T FSM
774 prev_state = m_t_state;
775 if (get_signal(PHI_488_IFC)) {
776 m_t_state = PHI_T_TIDS;
777 m_t_spms = false;
778 } else {
779 switch (m_t_state) {
780 case PHI_T_TIDS:
781 if (ton_msg()) {
782 m_t_state = PHI_T_TADS;
783 }
784 break;
785
786 case PHI_T_TADS:
787 if (!get_signal(PHI_488_ATN)) {
788 if (m_t_spms) {
789 m_t_state = PHI_T_SPAS;
790 } else {
791 m_t_state = PHI_T_TACS;
792 }
793 }
794 break;
795
796 case PHI_T_SPAS:
797 case PHI_T_TACS:
798 if (get_signal(PHI_488_ATN)) {
799 m_t_state = PHI_T_TADS;
800 }
801 break;
802
803 case PHI_T_ID1:
804 if (!get_signal(PHI_488_ATN)) {
805 m_t_state = PHI_T_ID2;
806 }
807 break;
808
809 case PHI_T_ID2:
810 if (get_signal(PHI_488_ATN)) {
811 m_t_state = PHI_T_ID1;
812 }
813 break;
814
815 case PHI_T_ID3:
816 if (!get_signal(PHI_488_ATN)) {
817 m_t_state = PHI_T_ID4;
818 }
819 break;
820
821 case PHI_T_ID4:
822 if (get_signal(PHI_488_ATN)) {
823 m_t_state = PHI_T_ID3;
824 }
825 break;
826
827 case PHI_T_ID5:
828 break;
829
830 default:
831 logerror("Invalid T state %d\n" , m_t_state);
832 m_t_state = PHI_T_TIDS;
833 }
834 }
835 if (m_t_state != prev_state) {
836 changed = true;
837 }
838 // No direct T outputs
839
840 // L FSM
841 prev_state = m_l_state;
842 if (get_signal(PHI_488_IFC)) {
843 m_l_state = PHI_L_LIDS;
844 } else {
845 switch (m_l_state) {
846 case PHI_L_LIDS:
847 if (lon_msg()) {
848 m_l_state = PHI_L_LADS;
849 }
850 break;
851
852 case PHI_L_LADS:
853 if (!get_signal(PHI_488_ATN)) {
854 m_l_state = PHI_L_LACS;
855 }
856 break;
857
858 case PHI_L_LACS:
859 if (get_signal(PHI_488_ATN)) {
860 m_l_state = PHI_L_LADS;
861 }
862 break;
863
864 default:
865 logerror("Invalid L state %d\n" , m_l_state);
866 m_l_state = PHI_L_LIDS;
867 }
868 }
869 if (m_l_state != prev_state) {
870 changed = true;
871 }
872 // No direct L outputs
873
874 // RL FSM
875 if (!get_signal(PHI_488_REN) && m_rl_rems) {
876 m_rl_rems = false;
877 changed = true;
878 }
879 // No direct RL outputs
880
881 // PP FSM
882 prev_state = m_pp_state;
883 switch (m_pp_state) {
884 case PHI_PP_PPIS:
885 break;
886
887 case PHI_PP_PPSS:
888 if (get_signal(PHI_488_ATN) && get_signal(PHI_488_EOI)) {
889 m_pp_state = PHI_PP_PPAS;
890 }
891 break;
892
893 case PHI_PP_PPAS:
894 if (!get_signal(PHI_488_ATN) || !get_signal(PHI_488_EOI)) {
895 m_pp_state = PHI_PP_PPSS;
896 }
897 break;
898
899 default:
900 logerror("Invalid PP state %d\n" , m_pp_state);
901 m_pp_state = PHI_PP_PPIS;
902 }
903 if (m_pp_state != prev_state) {
904 changed = true;
905 }
906 // PP outputs
907 if (m_pp_state == PHI_PP_PPAS && m_s_sense == !!BIT(m_reg_control , REG_CTRL_PP_RESPONSE_BIT)) {
908 LOG("%.6f PP %u\n" , machine().time().as_double() , m_ppr_msg);
909 dio_byte |= BIT_MASK<uint8_t>(m_ppr_msg);
910 }
911
912 // C FSM
913 prev_state = m_c_state;
914 if (!m_sys_controller && get_signal(PHI_488_IFC)) {
915 m_c_state = PHI_C_CIDS;
916 m_c_dly_timer->reset();
917 } else {
918 switch (m_c_state) {
919 case PHI_C_CIDS:
920 if (m_sys_controller && get_signal(PHI_488_IFC)) {
921 m_c_state = PHI_C_CADS;
922 }
923 break;
924
925 case PHI_C_CADS:
926 if (!get_signal(PHI_488_ATN)) {
927 m_c_state = PHI_C_CACS;
928 }
929 break;
930
931 case PHI_C_CACS:
932 // If there are ifcmds to send, just stay in CACS
933 // else wait for SH to finish its current transfer then decide what to do
934 if (nba_msg(new_byte , new_eoi) != NBA_CMD_FROM_OFIFO &&
935 m_sh_state != PHI_SH_STRS && m_sh_state != PHI_SH_SDYS) {
936 if (!m_fifo_out.empty()) {
937 // Possible cases
938 // D0/D1 Meaning of 1st word of OFIFO
939 // =====================================
940 // x0 Counted transfer enable or byte to be sent
941 // 11 Uncounted transfer enable
942 // 01 Send interface command (already caught by nba_msg)
943 m_c_state = PHI_C_CSBS;
944 m_be_counter = 0;
945 } else if (rpp_msg()) {
946 // Start parallel polling
947 m_c_state = PHI_C_CPPS;
948 }
949 // There's no third case: rpp_msg() is true when m_fifo_out.empty() is true
950 }
951 break;
952
953 case PHI_C_CPPS:
954 if (!rpp_msg()) {
955 m_c_state = PHI_C_CAWS;
956 m_c_dly_timer->adjust(attotime::from_nsec(DELAY_T9));
957 }
958 break;
959
960 case PHI_C_CSBS:
961 if (tcs_msg() && m_ah_state == PHI_AH_ANRS) {
962 m_c_state = PHI_C_CSHS;
963 m_c_dly_timer->adjust(attotime::from_nsec(DELAY_T10));
964 }
965 break;
966
967 case PHI_C_CSHS:
968 // tcs_msg cannot go false here
969 if (!m_c_dly_timer->enabled()) {
970 m_c_state = PHI_C_CSWS;
971 m_c_dly_timer->adjust(attotime::from_nsec(DELAY_T7));
972 }
973 break;
974
975 case PHI_C_CAWS:
976 if (rpp_msg()) {
977 m_c_state = PHI_C_CPPS;
978 m_c_dly_timer->reset();
979 } else if (!m_c_dly_timer->enabled()) {
980 m_c_state = PHI_C_CACS;
981 }
982 break;
983
984 case PHI_C_CTRS:
985 if (m_sh_state != PHI_SH_STRS) {
986 m_c_state = PHI_C_CIDS;
987 }
988 break;
989
990 case PHI_C_CSWS:
991 if (m_t_state == PHI_T_TADS || !m_c_dly_timer->enabled()) {
992 m_c_state = PHI_C_CAWS;
993 m_c_dly_timer->adjust(attotime::from_nsec(DELAY_T9));
994 }
995 break;
996
997 default:
998 logerror("Invalid C state %d\n" , m_c_state);
999 m_c_state = PHI_C_CIDS;
1000 }
1001 }
1002 if (m_c_state != prev_state) {
1003 changed = true;
1004 }
1005 // C outputs
1006 set_signal(PHI_488_ATN , m_c_state == PHI_C_CACS ||
1007 m_c_state == PHI_C_CPPS || m_c_state == PHI_C_CSWS ||
1008 m_c_state == PHI_C_CAWS || m_c_state == PHI_C_CTRS);
1009 eoi_signal = eoi_signal || m_c_state == PHI_C_CPPS;
1010 set_signal(PHI_488_EOI , eoi_signal);
1011 set_dio(dio_byte);
1012 }
1013
1014 // Update status register
1015 m_reg_status &= ~REG_STATUS_STATE_MASK;
1016 if (m_l_state != PHI_L_LIDS) {
1017 BIT_SET(m_reg_status, REG_STATUS_LISTEN_BIT);
1018 }
1019 if (m_t_state != PHI_T_TIDS) {
1020 BIT_SET(m_reg_status, REG_STATUS_TALK_BIT);
1021 }
1022 if (m_sys_controller) {
1023 BIT_SET(m_reg_status, REG_STATUS_SYS_CTRL_BIT);
1024 }
1025 if (controller_in_charge()) {
1026 BIT_SET(m_reg_status, REG_STATUS_CONTROLLER_BIT);
1027 }
1028 if (m_rl_rems) {
1029 BIT_SET(m_reg_status, REG_STATUS_REMOTE_BIT);
1030 }
1031
1032 // Update interrupting condition register and INT signal
1033 if (prev_cic != controller_in_charge()) {
1034 BIT_SET(m_reg_int_cond, REG_INT_STATUS_CH_BIT);
1035 }
1036 m_reg_int_cond &= ~REG_INT_STATE_MASK;
1037 if (m_fifo_out.empty()) {
1038 BIT_SET(m_reg_int_cond , REG_INT_FIFO_IDLE_BIT);
1039 }
1040 if (!m_fifo_in.empty()) {
1041 BIT_SET(m_reg_int_cond, REG_INT_FIFO_AV_BIT);
1042 }
1043 if (!m_fifo_out.full()) {
1044 BIT_SET(m_reg_int_cond, REG_INT_FIFO_ROOM_BIT);
1045 }
1046 if (controller_in_charge() && get_signal(PHI_488_SRQ)) {
1047 BIT_SET(m_reg_int_cond, REG_INT_SRQ_BIT);
1048 }
1049 update_pp();
1050 update_interrupt();
1051 update_dmarq();
1052
1053 m_no_recursion = false;
1054 }
1055
nba_msg(uint8_t & new_byte,bool & new_eoi) const1056 phi_device::nba_origin_t phi_device::nba_msg(uint8_t& new_byte , bool& new_eoi) const
1057 {
1058 if (controller_in_charge() && m_c_state == PHI_C_CACS && !m_fifo_out.empty()) {
1059 uint16_t word = m_fifo_out.peek();
1060 if ((word & REG_D0D1_MASK) == REG_OFIFO_IFCMD_MASK) {
1061 // Controller sends an interface command
1062 new_byte = (uint8_t)(word & IFCMD_MASK);
1063 if (!odd_parity(new_byte)) {
1064 BIT_SET(new_byte, 7);
1065 }
1066 new_eoi = false;
1067 return NBA_CMD_FROM_OFIFO;
1068 }
1069 }
1070
1071 switch (m_t_state) {
1072 case PHI_T_TACS:
1073 if (!BIT(m_reg_status , REG_STATUS_DATA_FREEZE_BIT) &&
1074 !BIT(m_reg_int_cond , REG_INT_DEV_CLEAR_BIT) &&
1075 !m_fifo_out.empty()) {
1076 uint16_t word = m_fifo_out.peek();
1077 if (!BIT(word , REG_OFIFO_SPECIAL_BIT)) {
1078 // Talker sends a data byte
1079 new_byte = (uint8_t)word;
1080 new_eoi = BIT(word , REG_OFIFO_END_BIT);
1081 return NBA_BYTE_FROM_OFIFO;
1082 }
1083 }
1084 break;
1085
1086 case PHI_T_SPAS:
1087 // Reply to serial poll: STB & RQS
1088 // TODO: check
1089 new_byte = m_sr_state == PHI_SR_NPRS ? 0x80 : 0x40;
1090 new_eoi = false;
1091 return NBA_FROM_SPAS;
1092
1093 case PHI_T_ID2:
1094 // 1st byte of ID
1095 new_byte = (uint8_t)m_reg_1st_id;
1096 new_eoi = false;
1097 return NBA_FROM_ID2;
1098
1099 case PHI_T_ID4:
1100 // 2nd byte of ID
1101 new_byte = (uint8_t)m_reg_2nd_id;
1102 new_eoi = true;
1103 return NBA_FROM_ID4;
1104
1105 default:
1106 break;
1107 }
1108 return NBA_NONE;
1109 }
1110
clear_nba(nba_origin_t origin)1111 void phi_device::clear_nba(nba_origin_t origin)
1112 {
1113 switch (origin) {
1114 case NBA_CMD_FROM_OFIFO:
1115 case NBA_BYTE_FROM_OFIFO:
1116 m_fifo_out.dequeue();
1117 break;
1118
1119 case NBA_FROM_ID2:
1120 m_t_state = PHI_T_ID3;
1121 break;
1122
1123 case NBA_FROM_ID4:
1124 m_t_state = PHI_T_ID5;
1125 break;
1126
1127 default:
1128 break;
1129 }
1130 }
1131
if_cmd_received(uint8_t byte)1132 bool phi_device::if_cmd_received(uint8_t byte)
1133 {
1134 LOG("%.6f RX cmd: %02x\n" , machine().time().as_double() , byte);
1135
1136 bool accepted = true;
1137
1138 if ((byte & IFCMD_AG_MASK) != IFCMD_SCG_VALUE) {
1139 // Any PCG clears sec. address recognition
1140 // Exceptions are intercepted below
1141 m_sa_state = PHI_SA_NONE;
1142 }
1143
1144 // TODO: IFC & non-reflection into controller
1145 switch (byte) {
1146 case IFCMD_GTL:
1147 // Go to local
1148 if (m_l_state == PHI_L_LADS) {
1149 m_rl_rems = false;
1150 }
1151 break;
1152
1153 case IFCMD_SDC:
1154 // Selected device clear
1155 if (m_l_state == PHI_L_LADS && !controller_in_charge()) {
1156 BIT_SET(m_reg_int_cond, REG_INT_DEV_CLEAR_BIT);
1157 }
1158 break;
1159
1160 case IFCMD_PPC:
1161 // Parallel poll configure
1162 if (m_l_state == PHI_L_LADS) {
1163 m_sa_state = PHI_SA_PACS;
1164 }
1165 break;
1166
1167 case IFCMD_GET:
1168 // Group execute trigger
1169 // TODO:
1170 break;
1171
1172 case IFCMD_TCT:
1173 // Take control
1174 if (m_c_state == PHI_C_CIDS && m_t_state == PHI_T_TADS) {
1175 // Take control
1176 m_c_state = PHI_C_CADS;
1177 }
1178 if (m_c_state == PHI_C_CACS && m_t_state != PHI_T_TADS) {
1179 // Give control to someone else
1180 m_c_state = PHI_C_CTRS;
1181 }
1182 break;
1183
1184 case IFCMD_LLO:
1185 // Local lock-out
1186 // Ignored
1187 break;
1188
1189 case IFCMD_DCL:
1190 // Device clear
1191 if (!controller_in_charge()) {
1192 BIT_SET(m_reg_int_cond, REG_INT_DEV_CLEAR_BIT);
1193 }
1194 break;
1195
1196 case IFCMD_PPU:
1197 // Parallel poll unconfigure
1198 if (m_pp_state == PHI_PP_PPSS) {
1199 m_pp_state = PHI_PP_PPIS;
1200 }
1201 break;
1202
1203 case IFCMD_SPE:
1204 // Serial poll enable
1205 m_t_spms = true;
1206 break;
1207
1208 case IFCMD_SPD:
1209 // Serial poll disable
1210 m_t_spms = false;
1211 break;
1212
1213 case IFCMD_UNL:
1214 // Unlisten
1215 if (!lon_msg()) {
1216 m_l_state = PHI_L_LIDS;
1217 }
1218 break;
1219
1220 case IFCMD_UNT:
1221 // Untalk
1222 if (ton_msg()) {
1223 m_t_state = PHI_T_TADS;
1224 } else {
1225 m_t_state = PHI_T_TIDS;
1226 }
1227 if (m_id_enabled) {
1228 m_sa_state = PHI_SA_UNT;
1229 }
1230 break;
1231
1232 default:
1233 {
1234 uint8_t address = byte & IFCMD_ADDR_MASK;
1235 uint8_t ag = byte & IFCMD_AG_MASK;
1236 bool my_addr = address == my_address();
1237
1238 if (ag == IFCMD_LAG_VALUE) {
1239 // LAG
1240 if (my_addr) {
1241 // MLA
1242 m_l_state = PHI_L_LADS;
1243 if (get_signal(PHI_488_REN)) {
1244 m_rl_rems = true;
1245 }
1246 m_sa_state = PHI_SA_LPAS;
1247 }
1248 } else if (ag == IFCMD_TAG_VALUE) {
1249 // TAG
1250 if (my_addr) {
1251 // MTA
1252 m_t_state = PHI_T_TADS;
1253 m_sa_state = PHI_SA_TPAS;
1254 } else if (!ton_msg()) {
1255 // OTA
1256 m_t_state = PHI_T_TIDS;
1257 }
1258 } else if (ag == IFCMD_SCG_VALUE) {
1259 // SCG
1260 switch (m_sa_state) {
1261 case PHI_SA_NONE:
1262 break;
1263
1264 case PHI_SA_PACS:
1265 if ((byte & IFCMD_PPX_MASK) == IFCMD_PPE_VALUE && m_pp_state == PHI_PP_PPIS) {
1266 // PPE
1267 m_s_sense = BIT(byte , IFCMD_PPE_S_BIT);
1268 m_ppr_msg = byte & IFCMD_PPE_PPR_MASK;
1269 LOG("PPE s=%d ppr=%u\n" , m_s_sense , m_ppr_msg);
1270 m_pp_state = PHI_PP_PPSS;
1271 } else if ((byte & IFCMD_PPX_MASK) == IFCMD_PPD_VALUE && m_pp_state == PHI_PP_PPSS) {
1272 // PPD
1273 m_pp_state = PHI_PP_PPIS;
1274 }
1275 break;
1276
1277 case PHI_SA_TPAS:
1278 case PHI_SA_LPAS:
1279 // command is a secondary address after MTA or MLA
1280 if (m_fifo_in.full() || BIT(m_reg_int_cond , REG_INT_DEV_CLEAR_BIT)) {
1281 // No room for secondary address in FIFO, stall handshake
1282 accepted = false;
1283 } else {
1284 uint16_t word = REG_IFIFO_2_ADDR_MASK | address;
1285 if (m_sa_state == PHI_SA_TPAS) {
1286 BIT_SET(word, REG_IFIFO_TALK_BIT);
1287 }
1288 rx_n_data_freeze(word);
1289 }
1290 break;
1291
1292 case PHI_SA_UNT:
1293 if (my_addr) {
1294 // Start IDENTIFY sequence
1295 m_t_state = PHI_T_ID1;
1296 } else {
1297 // Unaddressed by OSA (== UNT)
1298 if_cmd_received(IFCMD_UNT);
1299 }
1300 }
1301 }
1302 }
1303 }
1304 return accepted;
1305 }
1306
byte_received(uint8_t byte,bool eoi)1307 bool phi_device::byte_received(uint8_t byte , bool eoi)
1308 {
1309 // Start with D0/D1 = 00
1310 uint16_t word = byte;
1311
1312 if (eoi) {
1313 // EOI -> D0/D1 = 11
1314 word |= REG_IFIFO_LAST_MASK;
1315 }
1316
1317 bool end_of_transfer = false;
1318
1319 if (!m_fifo_out.empty() && m_c_state == PHI_C_CSBS && m_t_state != PHI_T_TACS) {
1320 uint16_t be_word = m_fifo_out.peek();
1321 // Monitoring bytes being transferred on the bus
1322 if (eoi) {
1323 end_of_transfer = true;
1324 } else if (!BIT(be_word , REG_OFIFO_LF_INH_BIT) && byte == 0x0a) {
1325 // LF received -> D0/D1 = 11
1326 word |= REG_IFIFO_LAST_MASK;
1327 end_of_transfer = true;
1328 } else if (be_word != REG_OFIFO_UNCNT_MASK && ((m_be_counter + 1) & 0xff) == (be_word & 0xff)) {
1329 // Byte count expired -> D0/D1 = 10
1330 word |= REG_IFIFO_CNT_EXP_MASK;
1331 end_of_transfer = true;
1332 }
1333 }
1334
1335 LOG("%.6f RX word:%04x\n" , machine().time().as_double() , word);
1336
1337 if (m_l_state == PHI_L_LACS) {
1338 if (m_fifo_in.full() || BIT(m_reg_int_cond , REG_INT_DEV_CLEAR_BIT)) {
1339 // No room for received byte, stall handshake
1340 LOG_NOISY("..stalled\n");
1341 return false;
1342 } else {
1343 LOG_NOISY("..OK\n");
1344 rx_n_data_freeze(word);
1345 }
1346 }
1347 if (end_of_transfer) {
1348 LOG_NOISY("End of byte transfer enable\n");
1349 m_fifo_out.dequeue();
1350 m_be_counter = 0;
1351 } else {
1352 m_be_counter++;
1353 }
1354
1355 return true;
1356 }
1357
rx_n_data_freeze(uint16_t word)1358 void phi_device::rx_n_data_freeze(uint16_t word)
1359 {
1360 m_fifo_in.enqueue(word);
1361 if (!controller_in_charge() && m_sh_state != PHI_SH_STRS) {
1362 // If PHI didn't send this byte to itself, set data freeze
1363 BIT_SET(m_reg_status, REG_STATUS_DATA_FREEZE_BIT);
1364 }
1365 }
1366
ton_msg(void) const1367 bool phi_device::ton_msg(void) const
1368 {
1369 return BIT(m_reg_address , REG_ADDR_TA_BIT);
1370 }
1371
lon_msg(void) const1372 bool phi_device::lon_msg(void) const
1373 {
1374 return BIT(m_reg_address , REG_ADDR_LA_BIT);
1375 }
1376
odd_parity(uint8_t byte) const1377 bool phi_device::odd_parity(uint8_t byte) const
1378 {
1379 byte = (byte >> 4) ^ byte;
1380 byte = (byte >> 2) ^ byte;
1381 byte = (byte >> 1) ^ byte;
1382 return (byte & 1) != 0;
1383 }
1384
my_address(void) const1385 uint8_t phi_device::my_address(void) const
1386 {
1387 if (m_sys_controller) {
1388 return CONTROLLER_ADDR;
1389 } else {
1390 return (m_reg_address >> REG_ADDR_HPIB_ADDR_BIT) & 0x1f;
1391 }
1392 }
1393
tcs_msg(void) const1394 bool phi_device::tcs_msg(void) const
1395 {
1396 uint8_t new_byte;
1397 bool new_eoi;
1398
1399 // When the CIC takes back control synchronously:
1400 // * Request to start parallel poll is pending (i.e. OFIFO is empty)
1401 // * There's an interface command to be sent at head of OFIFO
1402 return (m_c_state == PHI_C_CSBS || m_c_state == PHI_C_CSHS || m_c_state == PHI_C_CSWS) &&
1403 (rpp_msg() ||
1404 nba_msg(new_byte , new_eoi) == NBA_CMD_FROM_OFIFO);
1405 }
1406
rpp_msg(void) const1407 bool phi_device::rpp_msg(void) const
1408 {
1409 return m_fifo_out.empty();
1410 }
1411
get_pp_response()1412 uint8_t phi_device::get_pp_response()
1413 {
1414 return (get_dio() ^ m_reg_2nd_id) & m_reg_1st_id;
1415 }
1416
controller_in_charge(void) const1417 bool phi_device::controller_in_charge(void) const
1418 {
1419 return m_c_state != PHI_C_CIDS;
1420 }
1421
configure_pp_response()1422 void phi_device::configure_pp_response()
1423 {
1424 uint8_t addr = (m_reg_address >> REG_ADDR_HPIB_ADDR_BIT) & 0x1f;
1425 if (addr <= 7) {
1426 // If address <= 7, PP is automatically enabled and configured for PPR = ~address
1427 m_ppr_msg = addr ^ 7;
1428 m_pp_state = PHI_PP_PPSS;
1429 } else {
1430 m_ppr_msg = 0;
1431 m_pp_state = PHI_PP_PPIS;
1432 }
1433 m_s_sense = true;
1434 }
1435
update_pp()1436 void phi_device::update_pp()
1437 {
1438 if (m_c_state == PHI_C_CPPS) {
1439 if (m_fifo_in.empty() && get_pp_response()) {
1440 BIT_SET(m_reg_int_cond , REG_INT_PP_RESPONSE_BIT);
1441 } else {
1442 BIT_CLR(m_reg_int_cond , REG_INT_PP_RESPONSE_BIT);
1443 }
1444 update_interrupt();
1445 }
1446 }
1447
update_interrupt()1448 void phi_device::update_interrupt()
1449 {
1450 bool int_pending = (m_reg_int_cond & m_reg_int_mask) != 0;
1451 bool int_line = false;
1452 if (int_pending) {
1453 BIT_SET(m_reg_int_cond, REG_INT_PENDING_BIT);
1454 if (BIT(m_reg_int_mask , REG_INT_PENDING_BIT)) {
1455 int_line = true;
1456 }
1457 } else {
1458 BIT_CLR(m_reg_int_cond, REG_INT_PENDING_BIT);
1459 }
1460 if (int_line != m_int_line) {
1461 m_int_line = int_line;
1462 LOG_INT("INT %d\n" , m_int_line);
1463 m_int_write_func(m_int_line);
1464 }
1465 }
1466
update_dmarq()1467 void phi_device::update_dmarq()
1468 {
1469 bool new_dmarq_line;
1470 if (BIT(m_reg_control , REG_CTRL_DMA_FIFO_BIT)) {
1471 new_dmarq_line = BIT(m_reg_int_cond , REG_INT_FIFO_ROOM_BIT);
1472 } else {
1473 new_dmarq_line = BIT(m_reg_int_cond , REG_INT_FIFO_AV_BIT);
1474 }
1475 if (new_dmarq_line != m_dmarq_line) {
1476 m_dmarq_line = new_dmarq_line;
1477 LOG_INT("DRQ %d\n" , m_dmarq_line);
1478 m_dmarq_write_func(m_dmarq_line);
1479 }
1480 }
1481