1 // license:BSD-3-Clause
2 // copyright-holders: F. Ulivi
3 /*********************************************************************
4 
5     hp9895.cpp
6 
7     HP9895 floppy disk drive
8 
9     Phew, this one was tough!
10 
11     This is a dual 8" floppy disk drive that interfaces through
12     HPIB/IEEE-488 bus. It implements the so-called "Amigo" command
13     set.
14 
15     Its main components are:
16     * A Z80A CPU @ 4 MHz with 8 kB of firmware ROM and 1 kB of
17       static RAM
18     * A HP PHI chip that interfaces CPU to HPIB bus
19     * A disk controller implemented with a lot of discrete TTLs
20     * 2 MPI 8" disk drives
21 
22     Data I/O with the disk is carried out through 2 shift registers,
23     one for data bits (@ 0x60 address) and one for clock bits (@ 0x61
24     address). CPU is stalled by setting WAIT/ to 0 whenever it accesses
25     the data register and the hw is not ready for the byte. Once
26     the next byte boundary is reached (the SDOK signal activates) the
27     CPU is released and either the data byte is read from shift register
28     or written into it. At the same time clock shift register is
29     copied into clock register when reading or viceversa when writing.
30 
31     The 9895 drive can operate in 2 modes: HP/High density or IBM/low
32     density. This table summarizes the differences between the modes.
33     See also page 2-12 of service manual.
34 
35     | Characteristic | HP mode  | IBM mode  |
36     |----------------+----------+-----------|
37     | Bit cell size  | 2 µs     | 4 µs      |
38     | Modulation     | MMFM     | FM        |
39     | Bit order      | LS first | MS first  |
40     | Sync bytes     | 4x FF    | 6x 00     |
41     | Formatted size | 1155 kB  | 250.25 kB |
42 
43     Reference manual:
44     HP 09895-90030, feb 81, 9895A Flexible Disc Memory Service Manual
45 
46     Reference manual for the floppy drives:
47     Magnetic Peripherals, inc., feb 83, 9406-4 Flexible Disk Drive
48     Hardware Maintenance Manual
49 
50     TODO/Issues:
51     * floppy_image_device sometimes reports the wrong state for wpt
52       signal
53     * IBM mode hasn't been tested yet
54 
55 *********************************************************************/
56 
57 #include "emu.h"
58 #include "hp9895.h"
59 #include "formats/hpi_dsk.h"
60 
61 // Debugging
62 #define VERBOSE 1
63 #define LOG(x)  do { if (VERBOSE) logerror x; } while (0)
64 #define VERBOSE_0 0
65 #define LOG_0(x)  do { if (VERBOSE_0) logerror x; } while (0)
66 
67 // Macros to clear/set single bits
68 #define BIT_MASK(n) (1U << (n))
69 #define BIT_CLR(w , n)  ((w) &= ~BIT_MASK(n))
70 #define BIT_SET(w , n)  ((w) |= BIT_MASK(n))
71 
72 // Bits in RESET register
73 #define REG_RESET_TIMEOUT_START_BIT 0   // Start TIMEOUT oneshot (1)
74 #define REG_RESET_OVERUN_CLEAR_BIT  1   // Clear OVERUN (sic) (1)
75 #define REG_RESET_PROGRES_BIT       3   // PROGRES (1)
76 
77 // Bits in CNTL register
78 #define REG_CNTL_READON_BIT         1   // Enable reading (1)
79 #define REG_CNTL_WRITON_BIT         2   // Enable writing (1)
80 #define REG_CNTL_WRITDRV_BIT        3   // Enable writing to floppy (1)
81 #define REG_CNTL_CRCOUT_BIT         4   // Enable output of CRC word (1)
82 #define REG_CNTL_CRCON_BIT          5   // Enable updating of CRC word (1) or preset CRC to 0xffff (0)
83 
84 // Bits in DRV register
85 #define REG_DRV_STEP_BIT            0   // Step pulse to drive (1)
86 #define REG_DRV_MOVEIN_BIT          1   // Move heads inward (1)
87 #define REG_DRV_MGNENA_BIT          2   // Enable checking of bit cell margins (1)
88 #define REG_DRV_IN_USE_BIT          3   // "In use" signal to drive (1)
89 #define REG_DRV_LOWCURR_BIT         4   // Reduce write current in inner tracks (1)
90 #define REG_DRV_HEADSEL_BIT         7   // Head selection (1 = Head 1)
91 
92 // Bits in XV register
93 #define REG_XV_DRIVE3_BIT           0   // Select drive #3 (1)
94 #define REG_XV_DRIVE2_BIT           1   // Select drive #2 (1)
95 #define REG_XV_DRIVE1_BIT           2   // Select drive #1 (1)
96 #define REG_XV_DRIVE0_BIT           3   // Select drive #0 (1)
97 #define REG_XV_HIDEN_BIT            4   // Select HP/High density mode (1) or IBM/Low density mode (0)
98 #define REG_XV_PRECMP_BIT           5   // Enable pre-compensation
99 
100 // Bits in DRIVSTAT register
101 #define REG_DRIVSTAT_INDEX_BIT      0   // Index pulse from drive (1)
102 #define REG_DRIVSTAT_DISCHNG_BIT    1   // Disk changed (1)
103 #define REG_DRIVSTAT_TRACK0_BIT     2   // Heads on track #0 (1)
104 #define REG_DRIVSTAT_WRPROT_BIT     3   // Disk is write-protected (1)
105 #define REG_DRIVSTAT_READY_BIT      4   // Disk is ready (1)
106 #define REG_DRIVSTAT_CRCERR_BIT     5   // Error in CRC (1)
107 #define REG_DRIVSTAT_OVERUN_BIT     6   // I/O overrun between disk and CPU (1)
108 #define REG_DRIVSTAT_TWOSIDE_BIT    7   // 2-sided disk (1)
109 
110 // Bits in SWITCHES(2) registers
111 #define REG_SWITCHES_HPIB_ADDR_SHIFT    0   // LSB of HPIB address
112 #define REG_SWITCHES_HPIB_ADDR_MASK     7   // Mask of HPIB address
113 #define REG_SWITCHES_W_TEST_BIT     3   // "W" test push-button (1)
114 #define REG_SWITCHES_S_TEST_BIT     4   // "S" test push-button (1)
115 #define REG_SWITCHES_LOOP_BIT       5   // Test loop option (1)
116 #define REG_SWITCHES_TIMEOUT_BIT    6   // TIMEOUT (1)
117 #define REG_SWITCHES_AMDT_BIT       7   // Address mark detected (1)
118 
119 // Timers
120 enum {
121 	TIMEOUT_TMR_ID,
122 	BYTE_TMR_ID,
123 	HALF_BIT_TMR_ID
124 };
125 
126 // Timings
127 #define TIMEOUT_MSEC        450     // Timeout duration (ms)
128 #define HPMODE_BIT_FREQ     500000  // HP-mode bit frequency (Hz)
129 #define IBMMODE_BIT_FREQ    250000  // IBM-mode bit frequency (Hz)
130 
131 #define MIN_SYNC_BITS       29      // Number of bits to synchronize
132 
133 // device type definition
134 DEFINE_DEVICE_TYPE(HP9895, hp9895_device, "hp9895", "HP9895")
135 
136 // Masks of drive selectors in XV register
137 static const uint8_t xv_drive_masks[] = {
138 	BIT_MASK(REG_XV_DRIVE0_BIT),
139 	BIT_MASK(REG_XV_DRIVE1_BIT)
140 };
141 
hp9895_device(const machine_config & mconfig,const char * tag,device_t * owner,uint32_t clock)142 hp9895_device::hp9895_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
143 	: device_t(mconfig, HP9895, tag, owner, clock),
144 	  device_ieee488_interface(mconfig, *this),
145 	  m_cpu(*this , "cpu"),
146 	  m_phi(*this , "phi"),
147 	  m_drives{{*this , "floppy0"} , {*this , "floppy1"}},
148 	  m_switches{*this , "switches"}
149 {
150 }
151 
152 static INPUT_PORTS_START(hp9895_port)
153 	PORT_START("switches")
154 	PORT_CONFNAME(REG_SWITCHES_HPIB_ADDR_MASK << REG_SWITCHES_HPIB_ADDR_SHIFT , 0x00 , "HPIB address")
155 	PORT_CONFSETTING(0 << REG_SWITCHES_HPIB_ADDR_SHIFT , "0")
156 	PORT_CONFSETTING(1 << REG_SWITCHES_HPIB_ADDR_SHIFT , "1")
157 	PORT_CONFSETTING(2 << REG_SWITCHES_HPIB_ADDR_SHIFT , "2")
158 	PORT_CONFSETTING(3 << REG_SWITCHES_HPIB_ADDR_SHIFT , "3")
159 	PORT_CONFSETTING(4 << REG_SWITCHES_HPIB_ADDR_SHIFT , "4")
160 	PORT_CONFSETTING(5 << REG_SWITCHES_HPIB_ADDR_SHIFT , "5")
161 	PORT_CONFSETTING(6 << REG_SWITCHES_HPIB_ADDR_SHIFT , "6")
162 	PORT_CONFSETTING(7 << REG_SWITCHES_HPIB_ADDR_SHIFT , "7")
BIT_MASK(REG_SWITCHES_W_TEST_BIT)163 	PORT_CONFNAME(BIT_MASK(REG_SWITCHES_W_TEST_BIT) , 0x00 , "W Test")
164 	PORT_CONFSETTING(0x00 , DEF_STR(Off))
165 	PORT_CONFSETTING(BIT_MASK(REG_SWITCHES_W_TEST_BIT) , DEF_STR(On))
166 	PORT_CONFNAME(BIT_MASK(REG_SWITCHES_S_TEST_BIT) , 0x00 , "S Test")
167 	PORT_CONFSETTING(0x00 , DEF_STR(Off))
168 	PORT_CONFSETTING(BIT_MASK(REG_SWITCHES_S_TEST_BIT) , DEF_STR(On))
169 	PORT_CONFNAME(BIT_MASK(REG_SWITCHES_LOOP_BIT) , 0x00 , "Loop")
170 	PORT_CONFSETTING(0x00 , DEF_STR(Off))
171 	PORT_CONFSETTING(BIT_MASK(REG_SWITCHES_LOOP_BIT) , DEF_STR(On))
172 INPUT_PORTS_END
173 
174 ioport_constructor hp9895_device::device_input_ports() const
175 {
176 	return INPUT_PORTS_NAME(hp9895_port);
177 }
178 
device_start()179 void hp9895_device::device_start()
180 {
181 	save_item(NAME(m_cpu_irq));
182 	save_item(NAME(m_current_drive_idx));
183 	save_item(NAME(m_dskchg));
184 	save_item(NAME(m_crc));
185 	save_item(NAME(m_crcerr_syn));
186 	save_item(NAME(m_overrun));
187 	save_item(NAME(m_accdata));
188 	save_item(NAME(m_timeout));
189 	save_item(NAME(m_cntl_reg));
190 	save_item(NAME(m_clock_sr));
191 	save_item(NAME(m_clock_reg));
192 	save_item(NAME(m_data_sr));
193 	save_item(NAME(m_wr_context));
194 	save_item(NAME(m_had_transition));
195 	save_item(NAME(m_lckup));
196 	save_item(NAME(m_amdt));
197 	save_item(NAME(m_sync_cnt));
198 	save_item(NAME(m_hiden));
199 	save_item(NAME(m_mgnena));
200 
201 	m_timeout_timer = timer_alloc(TIMEOUT_TMR_ID);
202 	m_byte_timer = timer_alloc(BYTE_TMR_ID);
203 	m_half_bit_timer = timer_alloc(HALF_BIT_TMR_ID);
204 
205 	for (auto& d : m_drives) {
206 		d->get_device()->setup_ready_cb(floppy_image_device::ready_cb(&hp9895_device::floppy_ready_cb , this));
207 	}
208 }
209 
device_reset()210 void hp9895_device::device_reset()
211 {
212 	m_cpu_irq = false;
213 	m_current_drive = nullptr;
214 	m_current_drive_idx = ~0;
215 	for (auto& d : m_dskchg) {
216 		d = true;
217 	}
218 	preset_crc();
219 	m_crcerr_syn = false;
220 	m_overrun = false;
221 	m_accdata = false;
222 	m_timeout = true;
223 	m_cntl_reg = 0;
224 	m_clock_sr = 0;
225 	m_clock_reg = 0;
226 	m_data_sr = 0;
227 	m_wr_context = 0;
228 	m_had_transition = false;
229 	m_lckup = true; // Because READON = 0
230 	m_amdt = false;
231 	m_sync_cnt = 0;
232 	m_hiden = false;
233 	m_mgnena = false;
234 	m_timeout_timer->reset();
235 	m_byte_timer->reset();
236 	m_half_bit_timer->reset();
237 }
238 
device_timer(emu_timer & timer,device_timer_id id,int param,void * ptr)239 void hp9895_device::device_timer(emu_timer &timer, device_timer_id id, int param, void *ptr)
240 {
241 	switch (id) {
242 	case TIMEOUT_TMR_ID:
243 		LOG(("Timeout!\n"));
244 		m_timeout = true;
245 		if (m_mgnena) {
246 			// CPU is resumed by timeout if MGNENA=1
247 			m_cpu->trigger(1);
248 		}
249 		break;
250 
251 	case BYTE_TMR_ID:
252 		{
253 			if (m_accdata) {
254 				// Resume CPU when it's waiting for SDOK
255 				m_cpu->trigger(1);
256 			} else {
257 				// No access to data register by CPU
258 				LOG(("Data overrun!\n"));
259 				m_overrun = true;
260 			}
261 			m_accdata = false;
262 
263 			m_crcerr_syn = m_crc != 0;
264 
265 			if (!BIT(m_cntl_reg , REG_CNTL_CRCON_BIT)) {
266 				// CRC not enabled, keep it in preset state (all ones)
267 				preset_crc();
268 			}
269 
270 			attotime sdok_time{machine().time()};
271 			LOG_0(("SDOK @ %.06f\n" , sdok_time.as_double()));
272 			bool do_crc_upd = true;
273 			if (BIT(m_cntl_reg , REG_CNTL_WRITON_BIT)) {
274 				// Writing
275 				m_pll.commit(get_write_device() , sdok_time);
276 				m_pll.ctime = sdok_time;
277 
278 				// Check for AMDT when in loopback mode
279 				if (!m_lckup && !m_amdt && BIT(m_cntl_reg , REG_CNTL_READON_BIT)) {
280 					if (m_hiden) {
281 						m_amdt = m_data_sr != 0xff;
282 					} else {
283 						m_amdt = m_data_sr != 0;
284 					}
285 				}
286 
287 				LOG_0(("WR D=%02x/C=%02x\n" , m_data_sr , m_clock_sr));
288 				do_crc_upd = false;
289 				for (unsigned i = 0; i < 8; i++) {
290 					bool clock_bit;
291 					bool data_bit;
292 
293 					clock_bit = shift_sr(m_clock_sr, false);
294 					data_bit = shift_sr(m_data_sr, true);
295 
296 					if (BIT(m_cntl_reg , REG_CNTL_CRCOUT_BIT)) {
297 						// Substitute data bits from DSR with those from CRC when CRCOUT=1
298 						data_bit = BIT(m_crc , 15);
299 						m_crc <<= 1;
300 					} else if (BIT(m_cntl_reg , REG_CNTL_CRCON_BIT)) {
301 						// Update CRC
302 						update_crc(data_bit);
303 					}
304 					write_bit(data_bit, clock_bit);
305 				}
306 				// When shifting is done DSR is filled with 1s and CSR with 0s
307 			}
308 			if (BIT(m_cntl_reg , REG_CNTL_READON_BIT)) {
309 				// Reading
310 				m_pll.ctime = sdok_time;
311 
312 				for (unsigned i = 0; i < 8; i++) {
313 					read_bit(do_crc_upd);
314 				}
315 				LOG_0(("RD D=%02x/C=%02x\n" , m_data_sr , m_clock_sr));
316 			}
317 			LOG_0(("next SDOK @ %.06f\n" , m_pll.ctime.as_double()));
318 			timer.adjust(m_pll.ctime - sdok_time);
319 		}
320 		break;
321 
322 	case HALF_BIT_TMR_ID:
323 		{
324 			m_pll.ctime = machine().time();
325 			if (m_lckup) {
326 				// Trying to lock on synchronization bytes
327 				attotime edge;
328 				attotime tm;
329 				get_next_transition(m_pll.ctime, edge);
330 				bool half_bit0 = m_pll.feed_read_data(tm , edge , attotime::never);
331 				get_next_transition(m_pll.ctime, edge);
332 				bool half_bit1 = m_pll.feed_read_data(tm , edge , attotime::never);
333 				if (half_bit0 == half_bit1) {
334 					// If half bits are equal, no synch
335 					LOG_0(("Reset sync_cnt\n"));
336 					m_sync_cnt = 0;
337 				} else if (++m_sync_cnt >= MIN_SYNC_BITS) {
338 					// Synchronized, now wait for AM
339 					LOG_0(("Synchronized @ %.6f\n" , machine().time().as_double()));
340 					m_lckup = false;
341 					if (BIT(m_cntl_reg , REG_CNTL_WRITON_BIT)) {
342 						// When loopback is active, leave AM detection to byte timer as
343 						// byte boundary is already synchronized
344 						timer.reset();
345 						return;
346 					} else {
347 						// Align with bit cell
348 						// Synchronization bits in HP mode: 32x 1s -> C/D bits = 01010101...
349 						// Synchronization bits in IBM mode: 32x 0s -> C/D bits = 10101010...
350 						if (m_hiden != half_bit1) {
351 							// Discard 1/2 bit cell if synchronization achieved in the clock part
352 							get_next_transition(m_pll.ctime, edge);
353 							m_pll.feed_read_data(tm , edge , attotime::never);
354 						}
355 						// Load CSR & DSR as they are after synchronization bits
356 						if (m_hiden) {
357 							m_clock_sr = 0;
358 							m_data_sr = ~0;
359 						} else {
360 							m_clock_sr = ~0;
361 							m_data_sr = 0;
362 						}
363 					}
364 				}
365 			} else {
366 				// Looking for AM
367 				/// CRC is not updated because it can't be possibly enabled at this point
368 				read_bit(false);
369 				if ((m_hiden && !BIT(m_data_sr , 7)) ||
370 					(!m_hiden && BIT(m_data_sr , 0))) {
371 					// Got AM as soon as bits being shifted into DSR change value wrt synchronization bits
372 					m_amdt = true;
373 					// Finish the current byte
374 					for (unsigned i = 0; i < 7; i++) {
375 						read_bit(false);
376 					}
377 					attotime adjust{m_pll.ctime - machine().time()};
378 					LOG_0(("Got AM @ %.6f, ctime=%.6f, adj=%.6f, D=%02x/C=%02x\n" , machine().time().as_double() , m_pll.ctime.as_double() , adjust.as_double() , m_data_sr , m_clock_sr));
379 					// Disable half-bit timer & enable byte timer
380 					timer.reset();
381 					m_byte_timer->adjust(adjust);
382 					return;
383 				}
384 			}
385 			timer.adjust(m_pll.ctime - machine().time());
386 		}
387 		break;
388 
389 	default:
390 		break;
391 	}
392 }
393 
ieee488_eoi(int state)394 void hp9895_device::ieee488_eoi(int state)
395 {
396 	m_phi->eoi_w(state);
397 }
398 
ieee488_dav(int state)399 void hp9895_device::ieee488_dav(int state)
400 {
401 	m_phi->dav_w(state);
402 }
403 
ieee488_nrfd(int state)404 void hp9895_device::ieee488_nrfd(int state)
405 {
406 	m_phi->nrfd_w(state);
407 }
408 
ieee488_ndac(int state)409 void hp9895_device::ieee488_ndac(int state)
410 {
411 	m_phi->ndac_w(state);
412 }
413 
ieee488_ifc(int state)414 void hp9895_device::ieee488_ifc(int state)
415 {
416 	m_phi->ifc_w(state);
417 }
418 
ieee488_srq(int state)419 void hp9895_device::ieee488_srq(int state)
420 {
421 	m_phi->srq_w(state);
422 }
423 
ieee488_atn(int state)424 void hp9895_device::ieee488_atn(int state)
425 {
426 	m_phi->atn_w(state);
427 }
428 
ieee488_ren(int state)429 void hp9895_device::ieee488_ren(int state)
430 {
431 	m_phi->ren_w(state);
432 }
433 
WRITE_LINE_MEMBER(hp9895_device::phi_eoi_w)434 WRITE_LINE_MEMBER(hp9895_device::phi_eoi_w)
435 {
436 	m_bus->eoi_w(this , state);
437 }
438 
WRITE_LINE_MEMBER(hp9895_device::phi_dav_w)439 WRITE_LINE_MEMBER(hp9895_device::phi_dav_w)
440 {
441 	m_bus->dav_w(this , state);
442 }
443 
WRITE_LINE_MEMBER(hp9895_device::phi_nrfd_w)444 WRITE_LINE_MEMBER(hp9895_device::phi_nrfd_w)
445 {
446 	m_bus->nrfd_w(this , state);
447 }
448 
WRITE_LINE_MEMBER(hp9895_device::phi_ndac_w)449 WRITE_LINE_MEMBER(hp9895_device::phi_ndac_w)
450 {
451 	m_bus->ndac_w(this , state);
452 }
453 
WRITE_LINE_MEMBER(hp9895_device::phi_ifc_w)454 WRITE_LINE_MEMBER(hp9895_device::phi_ifc_w)
455 {
456 	m_bus->ifc_w(this , state);
457 }
458 
WRITE_LINE_MEMBER(hp9895_device::phi_srq_w)459 WRITE_LINE_MEMBER(hp9895_device::phi_srq_w)
460 {
461 	m_bus->srq_w(this , state);
462 }
463 
WRITE_LINE_MEMBER(hp9895_device::phi_atn_w)464 WRITE_LINE_MEMBER(hp9895_device::phi_atn_w)
465 {
466 	m_bus->atn_w(this , state);
467 }
468 
WRITE_LINE_MEMBER(hp9895_device::phi_ren_w)469 WRITE_LINE_MEMBER(hp9895_device::phi_ren_w)
470 {
471 	m_bus->ren_w(this , state);
472 }
473 
phi_dio_r()474 uint8_t hp9895_device::phi_dio_r()
475 {
476 	return m_bus->dio_r();
477 }
478 
phi_dio_w(uint8_t data)479 void hp9895_device::phi_dio_w(uint8_t data)
480 {
481 	m_bus->dio_w(this , data);
482 }
483 
WRITE_LINE_MEMBER(hp9895_device::phi_int_w)484 WRITE_LINE_MEMBER(hp9895_device::phi_int_w)
485 {
486 	m_cpu->set_input_line(INPUT_LINE_NMI , state);
487 	if (state) {
488 		// Ensure the event queue is emptied before executing any other instruction
489 		m_cpu->yield();
490 	}
491 }
492 
phi_reg_r(offs_t offset)493 uint8_t hp9895_device::phi_reg_r(offs_t offset)
494 {
495 	uint16_t reg = m_phi->reg16_r(offset);
496 
497 	// Reading D1=1 from a register sets the Z80 IRQ line
498 	if (BIT(reg , 14) && !m_cpu_irq) {
499 		m_cpu_irq = true;
500 		m_cpu->set_input_line(INPUT_LINE_IRQ0 , ASSERT_LINE);
501 	}
502 
503 	return (uint8_t)reg;
504 }
505 
z80_m1_w(uint8_t data)506 void hp9895_device::z80_m1_w(uint8_t data)
507 {
508 	// Every M1 cycle of Z80 clears the IRQ line
509 	if (m_cpu_irq) {
510 		m_cpu_irq = false;
511 		m_cpu->set_input_line(INPUT_LINE_IRQ0 , CLEAR_LINE);
512 	}
513 }
514 
data_w(uint8_t data)515 void hp9895_device::data_w(uint8_t data)
516 {
517 	LOG_0(("W DATA=%02x\n" , data));
518 	// CPU stalls until next SDOK
519 	m_cpu->suspend_until_trigger(1 , true);
520 	m_data_sr = data;
521 	m_clock_sr = m_clock_reg;
522 	m_accdata = true;
523 }
524 
clock_w(uint8_t data)525 void hp9895_device::clock_w(uint8_t data)
526 {
527 	LOG_0(("W CLOCK=%02x\n" , data));
528 	m_clock_reg = data;
529 }
530 
reset_w(uint8_t data)531 void hp9895_device::reset_w(uint8_t data)
532 {
533 	LOG_0(("W RESET=%02x\n" , data));
534 	if (BIT(data , REG_RESET_TIMEOUT_START_BIT)) {
535 		m_timeout = false;
536 		m_timeout_timer->adjust(attotime::from_msec(TIMEOUT_MSEC));
537 	}
538 	if (BIT(data , REG_RESET_OVERUN_CLEAR_BIT)) {
539 		m_overrun = false;
540 	}
541 	// TODO: PROGRES
542 }
543 
leds_w(uint8_t data)544 void hp9895_device::leds_w(uint8_t data)
545 {
546 	LOG(("W LEDS=%02x %c%c%c%c%c\n" , data , BIT(data , 4) ? '.' : '*' , BIT(data , 3) ? '.' : '*' , BIT(data , 2) ? '.' : '*' , BIT(data , 1) ? '.' : '*' , BIT(data , 0) ? '.' : '*'));
547 	// TODO:
548 }
549 
cntl_w(uint8_t data)550 void hp9895_device::cntl_w(uint8_t data)
551 {
552 	if (data != m_cntl_reg) {
553 		LOG_0(("W CNTL=%02x -> %02x\n" , m_cntl_reg , data));
554 		uint8_t old_cntl_reg = m_cntl_reg;
555 		m_cntl_reg = data;
556 
557 		bool old_writon = BIT(old_cntl_reg , REG_CNTL_WRITON_BIT);
558 		bool new_writon = BIT(m_cntl_reg , REG_CNTL_WRITON_BIT);
559 		bool old_readon = BIT(old_cntl_reg , REG_CNTL_READON_BIT);
560 		bool new_readon = BIT(m_cntl_reg , REG_CNTL_READON_BIT);
561 
562 		bool byte_timer_running = old_writon || m_amdt;
563 		bool byte_timer_needed = new_writon || (new_readon && m_amdt);
564 
565 		if (!byte_timer_running && byte_timer_needed) {
566 			LOG_0(("Enable byte tmr\n"));
567 			attotime byte_period = get_half_bit_cell_period() * 16;
568 			m_byte_timer->adjust(byte_period);
569 		} else if (byte_timer_running && !byte_timer_needed) {
570 			LOG_0(("Disable byte tmr\n"));
571 			m_byte_timer->reset();
572 		}
573 
574 		if (!old_writon && !old_readon && (new_writon || new_readon)) {
575 			m_pll.set_clock(get_half_bit_cell_period());
576 		}
577 
578 		if (!old_writon && new_writon) {
579 			// Writing enabled
580 			LOG_0(("Start writing..\n"));
581 			m_pll.start_writing(machine().time());
582 			m_wr_context = 0;
583 			m_had_transition = false;
584 		} else if (old_writon && !new_writon) {
585 			// Writing disabled
586 			LOG_0(("Stop writing..\n"));
587 			m_pll.stop_writing(get_write_device() , machine().time());
588 		}
589 		if (!old_readon && new_readon) {
590 			// Reading enabled
591 			LOG_0(("Start reading..\n"));
592 			m_pll.read_reset(machine().time());
593 			m_sync_cnt = 0;
594 			m_half_bit_timer->adjust(get_half_bit_cell_period());
595 		} else if (old_readon && !new_readon) {
596 			// Reading disabled
597 			LOG_0(("Stop reading..\n"));
598 			m_half_bit_timer->reset();
599 			m_lckup = true;
600 			m_amdt = false;
601 		}
602 		if (!new_readon && !new_writon) {
603 			m_crcerr_syn = false;
604 			BIT_CLR(m_cntl_reg, REG_CNTL_CRCON_BIT);
605 			BIT_CLR(m_cntl_reg, REG_CNTL_CRCOUT_BIT);
606 			preset_crc();
607 		}
608 	}
609 }
610 
drv_w(uint8_t data)611 void hp9895_device::drv_w(uint8_t data)
612 {
613 	LOG_0(("W DRV=%02x\n" , data));
614 	m_mgnena = BIT(data , REG_DRV_MGNENA_BIT);
615 	if (m_current_drive != nullptr) {
616 		m_current_drive->stp_w(!BIT(data , REG_DRV_STEP_BIT));
617 		m_current_drive->dir_w(!BIT(data , REG_DRV_MOVEIN_BIT));
618 		// TODO: in use signal
619 		m_current_drive->ss_w(BIT(data , REG_DRV_HEADSEL_BIT));
620 	}
621 }
622 
xv_w(uint8_t data)623 void hp9895_device::xv_w(uint8_t data)
624 {
625 	LOG_0(("W XV=%02x\n" , data));
626 	// Disk Changed flag is cleared when drive is ready and it is deselected
627 	if (m_current_drive_idx < 2 && (data & xv_drive_masks[ m_current_drive_idx ]) == 0 && !m_current_drive->ready_r()) {
628 		if (m_dskchg[ m_current_drive_idx ]) {
629 			LOG(("Dskchg %u cleared\n" , m_current_drive_idx));
630 		}
631 		m_dskchg[ m_current_drive_idx ] = false;
632 	}
633 
634 	m_current_drive = nullptr;
635 	m_current_drive_idx = ~0;
636 	for (unsigned i = 0; i < 2; i++) {
637 		if (data & xv_drive_masks[ i ]) {
638 			m_current_drive = m_drives[ i ]->get_device();
639 			m_current_drive_idx = i;
640 			break;
641 		}
642 	}
643 
644 	m_hiden = BIT(data , REG_XV_HIDEN_BIT);
645 }
646 
data_r()647 uint8_t hp9895_device::data_r()
648 {
649 	m_clock_reg = m_clock_sr;
650 	m_accdata = true;
651 	LOG_0(("R DATA=%02x\n" , m_data_sr));
652 	// CPU stalls until next SDOK
653 	m_cpu->suspend_until_trigger(1 , true);
654 	return m_data_sr;
655 }
656 
clock_r()657 uint8_t hp9895_device::clock_r()
658 {
659 	return m_clock_reg;
660 }
661 
drivstat_r()662 uint8_t hp9895_device::drivstat_r()
663 {
664 	uint8_t res = 0;
665 
666 	if (m_current_drive != nullptr) {
667 		if (m_current_drive->idx_r()) {
668 			BIT_SET(res , REG_DRIVSTAT_INDEX_BIT);
669 		}
670 		if (m_dskchg[ m_current_drive_idx ]) {
671 			BIT_SET(res , REG_DRIVSTAT_DISCHNG_BIT);
672 		}
673 		if (!m_current_drive->trk00_r()) {
674 			BIT_SET(res , REG_DRIVSTAT_TRACK0_BIT);
675 		}
676 		if (m_current_drive->wpt_r()) {
677 			BIT_SET(res , REG_DRIVSTAT_WRPROT_BIT);
678 		}
679 		if (!m_current_drive->ready_r()) {
680 			BIT_SET(res , REG_DRIVSTAT_READY_BIT);
681 		}
682 		if (!m_current_drive->twosid_r()) {
683 			BIT_SET(res , REG_DRIVSTAT_TWOSIDE_BIT);
684 		}
685 	}
686 	if (m_crcerr_syn) {
687 		BIT_SET(res , REG_DRIVSTAT_CRCERR_BIT);
688 	}
689 	if (m_overrun) {
690 		BIT_SET(res , REG_DRIVSTAT_OVERUN_BIT);
691 	}
692 	LOG_0(("R DRIVSTAT=%02x\n" , res));
693 	return res;
694 }
695 
switches_r()696 uint8_t hp9895_device::switches_r()
697 {
698 	uint8_t res = get_switches2();
699 	res |= m_switches->read();
700 	return res;
701 }
702 
switches2_r()703 uint8_t hp9895_device::switches2_r()
704 {
705 	return get_switches2();
706 }
707 
floppy_ready_cb(floppy_image_device * floppy,int state)708 void hp9895_device::floppy_ready_cb(floppy_image_device *floppy , int state)
709 {
710 	if (state) {
711 		// Set Disk Changed flag when a drive is not ready
712 		for (unsigned i = 0; i < 2; i++) {
713 			if (floppy == m_drives[ i ]->get_device()) {
714 				LOG(("Dskchg %u set\n" , i));
715 				m_dskchg[ i ] = true;
716 				break;
717 			}
718 		}
719 	}
720 }
721 
get_switches2(void) const722 uint8_t hp9895_device::get_switches2(void) const
723 {
724 	uint8_t res = 0;
725 
726 	if (m_timeout) {
727 		BIT_SET(res, REG_SWITCHES_TIMEOUT_BIT);
728 	}
729 	if (m_amdt) {
730 		BIT_SET(res, REG_SWITCHES_AMDT_BIT);
731 	}
732 
733 	return res;
734 }
735 
get_half_bit_cell_period(void) const736 attotime hp9895_device::get_half_bit_cell_period(void) const
737 {
738 	return attotime::from_hz((m_hiden ? HPMODE_BIT_FREQ : IBMMODE_BIT_FREQ) * 2);
739 }
740 
get_write_device(void) const741 floppy_image_device *hp9895_device::get_write_device(void) const
742 {
743 	if (!BIT(m_cntl_reg , REG_CNTL_WRITDRV_BIT)) {
744 		return nullptr;
745 	} else {
746 		return m_current_drive;
747 	}
748 }
749 
preset_crc(void)750 void hp9895_device::preset_crc(void)
751 {
752 	m_crc = ~0;
753 }
754 
update_crc(bool bit)755 void hp9895_device::update_crc(bool bit)
756 {
757 	bool msb = BIT(m_crc , 15);
758 
759 	m_crc <<= 1;
760 	if (bit ^ msb) {
761 		m_crc ^= 0x1021;
762 	}
763 }
764 
shift_sr(uint8_t & sr,bool input_bit)765 bool hp9895_device::shift_sr(uint8_t& sr , bool input_bit)
766 {
767 	bool res;
768 
769 	if (m_hiden) {
770 		res = BIT(sr , 0);
771 		sr >>= 1;
772 		if (input_bit) {
773 			BIT_SET(sr , 7);
774 		}
775 	} else {
776 		res = BIT(sr , 7);
777 		sr <<= 1;
778 		if (input_bit) {
779 			BIT_SET(sr , 0);
780 		}
781 	}
782 	return res;
783 }
784 
get_next_transition(const attotime & from_when,attotime & edge)785 void hp9895_device::get_next_transition(const attotime& from_when , attotime& edge)
786 {
787 	edge = attotime::never;
788 
789 	if (BIT(m_cntl_reg , REG_CNTL_WRITON_BIT)) {
790 		// Loop back write transitions into reading data path
791 		for (int idx = 0; idx < m_pll.write_position; idx++) {
792 			if (m_pll.write_buffer[ idx ] >= from_when) {
793 				edge = m_pll.write_buffer[ idx ];
794 				break;
795 			}
796 		}
797 	} else if (m_current_drive != nullptr) {
798 		edge = m_current_drive->get_next_transition(from_when);
799 	}
800 }
801 
read_bit(bool crc_upd)802 void hp9895_device::read_bit(bool crc_upd)
803 {
804 	attotime edge;
805 	attotime tm;
806 
807 	get_next_transition(m_pll.ctime, edge);
808 	bool clock_bit = m_pll.feed_read_data(tm , edge , attotime::never);
809 	get_next_transition(m_pll.ctime, edge);
810 	bool data_bit = m_pll.feed_read_data(tm , edge , attotime::never);
811 
812 	shift_sr(m_clock_sr, clock_bit);
813 	data_bit = shift_sr(m_data_sr, data_bit);
814 
815 	if (crc_upd &&
816 		BIT(m_cntl_reg , REG_CNTL_CRCON_BIT) &&
817 		!BIT(m_cntl_reg , REG_CNTL_CRCOUT_BIT)) {
818 		update_crc(data_bit);
819 	}
820 }
821 
write_bit(bool data_bit,bool clock_bit)822 void hp9895_device::write_bit(bool data_bit , bool clock_bit)
823 {
824 	if (m_hiden) {
825 		// **** HP mode ****
826 		// m_wr_context delays data bits by 2 bit cells
827 		// Bit  Content
828 		// ============
829 		// 2    Data @ t-2
830 		// 1    Data @ t-1
831 		// 0    Data @ t
832 		m_wr_context = (m_wr_context << 1) | data_bit;
833 		data_bit = BIT(m_wr_context , 2);
834 		clock_bit = !data_bit && (clock_bit || !m_had_transition);
835 		m_had_transition = data_bit || clock_bit;
836 	}
837 	// else... IBM mode, nothing to do
838 
839 	attotime dummy;
840 
841 	m_pll.write_next_bit(clock_bit , dummy , nullptr , attotime::never);
842 	m_pll.write_next_bit(data_bit , dummy , nullptr , attotime::never);
843 }
844 
845 ROM_START(hp9895)
846 	ROM_REGION(0x2000 , "cpu" , 0)
CRC(b50dbfb5)847 	ROM_LOAD("1818-1391a.bin" , 0 , 0x2000 , CRC(b50dbfb5) SHA1(96edf9af78be75fbad2a0245b8af43958ba32752))
848 ROM_END
849 
850 void hp9895_device::z80_program_map(address_map &map)
851 {
852 	map.unmap_value_high();
853 	map(0x0000, 0x1fff).rom().region("cpu", 0);
854 	map(0x6000, 0x63ff).ram();
855 }
856 
z80_io_map(address_map & map)857 void hp9895_device::z80_io_map(address_map &map)
858 {
859 	map.unmap_value_high();
860 	map.global_mask(0xff);
861 	map(0x10, 0x17).w("phi", FUNC(phi_device::reg8_w)).r(FUNC(hp9895_device::phi_reg_r));
862 	map(0x60, 0x60).rw(FUNC(hp9895_device::data_r), FUNC(hp9895_device::data_w));
863 	map(0x61, 0x61).rw(FUNC(hp9895_device::clock_r), FUNC(hp9895_device::clock_w));
864 	map(0x62, 0x62).rw(FUNC(hp9895_device::drivstat_r), FUNC(hp9895_device::reset_w));
865 	map(0x63, 0x63).rw(FUNC(hp9895_device::switches_r), FUNC(hp9895_device::leds_w));
866 	map(0x64, 0x64).w(FUNC(hp9895_device::cntl_w));
867 	map(0x65, 0x65).w(FUNC(hp9895_device::drv_w));
868 	map(0x66, 0x66).w(FUNC(hp9895_device::xv_w));
869 	map(0x67, 0x67).r(FUNC(hp9895_device::switches2_r));
870 }
871 
hp9895_floppies(device_slot_interface & device)872 static void hp9895_floppies(device_slot_interface &device)
873 {
874 	device.option_add("8dsdd" , FLOPPY_8_DSDD);
875 }
876 
877 static const floppy_format_type hp9895_floppy_formats[] = {
878 	FLOPPY_MFI_FORMAT,
879 	FLOPPY_HPI_FORMAT,
880 	nullptr
881 };
882 
device_rom_region() const883 const tiny_rom_entry *hp9895_device::device_rom_region() const
884 {
885 	return ROM_NAME(hp9895);
886 }
887 
device_add_mconfig(machine_config & config)888 void hp9895_device::device_add_mconfig(machine_config &config)
889 {
890 	Z80(config, m_cpu, 4000000);
891 	m_cpu->set_addrmap(AS_PROGRAM, &hp9895_device::z80_program_map);
892 	m_cpu->set_addrmap(AS_IO, &hp9895_device::z80_io_map);
893 	m_cpu->refresh_cb().set(FUNC(hp9895_device::z80_m1_w));
894 
895 	PHI(config, m_phi, 0);
896 	m_phi->eoi_write_cb().set(FUNC(hp9895_device::phi_eoi_w));
897 	m_phi->dav_write_cb().set(FUNC(hp9895_device::phi_dav_w));
898 	m_phi->nrfd_write_cb().set(FUNC(hp9895_device::phi_nrfd_w));
899 	m_phi->ndac_write_cb().set(FUNC(hp9895_device::phi_ndac_w));
900 	m_phi->ifc_write_cb().set(FUNC(hp9895_device::phi_ifc_w));
901 	m_phi->srq_write_cb().set(FUNC(hp9895_device::phi_srq_w));
902 	m_phi->atn_write_cb().set(FUNC(hp9895_device::phi_atn_w));
903 	m_phi->ren_write_cb().set(FUNC(hp9895_device::phi_ren_w));
904 	m_phi->dio_read_cb().set(FUNC(hp9895_device::phi_dio_r));
905 	m_phi->dio_write_cb().set(FUNC(hp9895_device::phi_dio_w));
906 	m_phi->int_write_cb().set(FUNC(hp9895_device::phi_int_w));
907 	m_phi->sys_cntrl_read_cb().set_constant(0);
908 
909 	FLOPPY_CONNECTOR(config, "floppy0", hp9895_floppies, "8dsdd", hp9895_floppy_formats).set_fixed(true);
910 	FLOPPY_CONNECTOR(config, "floppy1", hp9895_floppies, "8dsdd", hp9895_floppy_formats).set_fixed(true);
911 }
912