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