1 // license:BSD-3-Clause
2 // copyright-holders:Roberto Lavarone
3 /***********************************************************************
4
5 machine/z80ne.c
6
7 Functions to emulate general aspects of the machine (RAM, ROM,
8 interrupts, I/O ports)
9
10 ***********************************************************************/
11
12 /* Core includes */
13 #include "emu.h"
14 #include "includes/z80ne.h"
15
16 //#define VERBOSE 1
17 #include "logmacro.h"
18
19
20
21
22
23 /* timer to read cassette waveforms */
24
cassette_device_image()25 cassette_image_device* z80ne_state::cassette_device_image()
26 {
27 if (m_lx385_ctrl & 0x08)
28 return m_cassette2;
29 else
30 return m_cassette1;
31 }
32
TIMER_CALLBACK_MEMBER(z80ne_state::z80ne_cassette_tc)33 TIMER_CALLBACK_MEMBER(z80ne_state::z80ne_cassette_tc)
34 {
35 uint8_t cass_ws = 0;
36 m_cass_data.input.length++;
37
38 cass_ws = ((cassette_device_image())->input() > +0.02) ? 1 : 0;
39
40 if ((cass_ws ^ m_cass_data.input.level) & cass_ws)
41 {
42 m_cass_data.input.level = cass_ws;
43 m_cass_data.input.bit = ((m_cass_data.input.length < m_cass_data.wave_filter) || (m_cass_data.input.length > 0x20)) ? 1 : 0;
44 m_cass_data.input.length = 0;
45 m_uart->write_si(m_cass_data.input.bit);
46 }
47 m_cass_data.input.level = cass_ws;
48
49 /* saving a tape - convert the serial stream from the uart */
50
51 m_cass_data.output.length--;
52
53 if (!(m_cass_data.output.length))
54 {
55 if (m_cass_data.output.level)
56 m_cass_data.output.level = 0;
57 else
58 {
59 m_cass_data.output.level=1;
60 cass_ws = m_uart->so_r();
61 m_cass_data.wave_length = cass_ws ? m_cass_data.wave_short : m_cass_data.wave_long;
62 }
63 cassette_device_image()->output(m_cass_data.output.level ? -1.0 : +1.0);
64 m_cass_data.output.length = m_cass_data.wave_length;
65 }
66 }
67
save_state_vars()68 void z80ne_state::save_state_vars()
69 {
70 save_item(NAME(m_lx383_scan_counter));
71 save_item(NAME(m_lx383_key));
72 save_item(NAME(m_lx383_downsampler));
73 save_item(NAME(m_lx385_ctrl));
74 }
75
init_z80ne()76 void z80ne_state::init_z80ne()
77 {
78 save_state_vars();
79 }
80
driver_init()81 void z80netf_state::driver_init()
82 {
83 save_state_vars();
84
85 /* first two entries point to rom on reset */
86 u8 *r = m_ram->pointer();
87 m_bank1->configure_entry(0, r); /* RAM at 0x0000-0x03FF */
88 m_bank1->configure_entries(1, 3, m_rom+0x4400, 0x0400); /* ep390, ep1390, ep2390 at 0x0000-0x03FF */
89 m_bank1->configure_entry(4, m_rom+0x4000); /* ep382 at 0x0000-0x03FF */
90 m_bank1->configure_entry(5, m_rom); /* ep548 at 0x0000-0x03FF */
91
92 m_bank2->configure_entry(0, r+0x0400); /* RAM at 0x0400 */
93 m_bank2->configure_entry(1, m_rom+0x0400); /* ep548 at 0x0400-0x3FFF */
94
95 m_bank3->configure_entry(0, r+0x4000); /* RAM at 0x8000 */
96 m_bank3->configure_entry(1, m_rom+0x4000); /* ep382 at 0x8000 */
97
98 m_bank4->configure_entry(0, r+0x5000); /* RAM at 0xF000 */
99 m_bank4->configure_entries(1, 3, m_rom+0x4400, 0x0400); /* ep390, ep1390, ep2390 at 0xF000 */
100
101 }
102
TIMER_CALLBACK_MEMBER(z80ne_state::z80ne_kbd_scan)103 TIMER_CALLBACK_MEMBER(z80ne_state::z80ne_kbd_scan)
104 {
105 /*
106 * NE555 is connected to a 74LS93 binary counter
107 * 74LS93 output:
108 * QA-QC: column index for LEDs and keyboard
109 * QD: keyboard row select
110 *
111 * Port F0 input bit assignment:
112 * 0 QA bits 0..3 of row counter
113 * 1 QB
114 * 2 QC
115 * 3 QD
116 * 4 Control button pressed, active high
117 * 5 Always low
118 * 6 Always low
119 * 7 Selected button pressed, active low
120 *
121 *
122 */
123
124 uint16_t key_bits;
125 uint8_t ctrl; //, rst;
126 uint8_t i;
127
128 /* 4-bit counter */
129 --m_lx383_scan_counter;
130 m_lx383_scan_counter &= 0x0f;
131
132 if ( --m_lx383_downsampler == 0 )
133 {
134 m_lx383_downsampler = LX383_DOWNSAMPLING;
135 key_bits = (m_io_row1->read() << 8) | m_io_row0->read();
136 // rst = m_io_rst->read();
137 ctrl = m_io_ctrl->read();
138
139 for ( i = 0; i<LX383_KEYS; i++)
140 {
141 m_lx383_key[i] = ( i | (key_bits & 0x01 ? 0x80 : 0x00) | ~ctrl);
142 key_bits >>= 1;
143 }
144 }
145 }
146
device_timer(emu_timer & timer,device_timer_id id,int param,void * ptr)147 void z80ne_state::device_timer(emu_timer &timer, device_timer_id id, int param, void *ptr)
148 {
149 switch (id)
150 {
151 case 0:
152 m_maincpu->pulse_input_line(INPUT_LINE_NMI, attotime::zero);
153 break;
154 default:
155 printf("Invalid timer %d encountered\n",id);
156 }
157 }
158
reset_lx387()159 void z80net_state::reset_lx387()
160 {
161 m_lx387_kr2376->set_input_pin( kr2376_device::KR2376_DSII, 0);
162 m_lx387_kr2376->set_input_pin( kr2376_device::KR2376_PII, 0);
163 }
164
reset_lx390_banking()165 void z80netf_state::reset_lx390_banking()
166 {
167 switch (m_io_config->read() & 0x07)
168 {
169 case 0x01: /* EP382 Hex Monitor */
170 if (VERBOSE)
171 logerror("reset_lx390_banking: banking ep382\n");
172 m_bank1->set_entry(4); /* ep382 at 0x0000 for 3 cycles, then RAM */
173 m_bank2->set_entry(0); /* RAM at 0x0400 */
174 m_bank3->set_entry(1); /* ep382 at 0x8000 */
175 m_bank4->set_entry(0); /* RAM at 0xF000 */
176 break;
177 case 0x02: /* EP548 16k BASIC */
178 if (VERBOSE)
179 logerror("reset_lx390_banking: banking ep548\n");
180 m_bank1->set_entry(5); /* ep548 at 0x0000-0x03FF */
181 m_bank2->set_entry(1); /* ep548 at 0x0400-0x3FFF */
182 m_bank3->set_entry(0); /* RAM at 0x8000 */
183 m_bank4->set_entry(0); /* RAM at 0xF000 */
184 break;
185 case 0x03: /* EP390 Boot Loader for 5.5k floppy BASIC */
186 if (VERBOSE)
187 logerror("reset_lx390_banking: banking ep390\n");
188 m_bank1->set_entry(1); /* ep390 at 0x0000-0 x03FF for 3 cycles, then RAM */
189 m_bank2->set_entry(0); /* RAM at 0x0400-0x3FFF */
190 m_bank3->set_entry(0); /* RAM at 0x8000 */
191 m_bank4->set_entry(1); /* ep390 at 0xF000 */
192 break;
193 case 0x04: /* EP1390 Boot Loader for NE DOS 1.0/1.5 */
194 if (VERBOSE)
195 logerror("reset_lx390_banking: banking ep1390\n");
196 m_bank1->set_entry(2); /* ep1390 at 0x0000-0x03FF for 3 cycles, then RAM */
197 m_bank2->set_entry(0); /* RAM at 0x0400-0x3FFF */
198 m_bank3->set_entry(0); /* RAM at 0x8000 */
199 m_bank4->set_entry(2); /* ep1390 at 0xF000 */
200 break;
201 case 0x05: /* EP2390 Boot Loader for NE DOS G.1 */
202 if (VERBOSE)
203 logerror("reset_lx390_banking: banking ep2390\n");
204 m_bank1->set_entry(3); /* ep2390 at 0x0000-0x03FF for 3 cycles, then RAM */
205 m_bank2->set_entry(0); /* RAM at 0x0400-0x3FFF */
206 m_bank3->set_entry(0); /* RAM at 0x8000 */
207 m_bank4->set_entry(3); /* ep2390 at 0xF000 */
208 break;
209 }
210
211 /* TODO: in real hardware the ENH bus line is pulled down
212 * until a I/O read is performed on a address with A0 address bit low and A1 or A2 address bit high
213 */
214 }
215
base_reset()216 void z80ne_state::base_reset()
217 {
218 for (int i = 0; i < LX383_KEYS; i++)
219 m_lx383_key[i] = 0xf0 | i;
220 m_lx383_scan_counter = 0x0f;
221 m_lx383_downsampler = LX383_DOWNSAMPLING;
222
223 /* Initialize cassette interface */
224 switch(m_io_lx_385->read() & 0x07)
225 {
226 case 0x01:
227 m_cass_data.speed = TAPE_300BPS;
228 m_cass_data.wave_filter = LX385_TAPE_SAMPLE_FREQ / 1600;
229 m_cass_data.wave_short = LX385_TAPE_SAMPLE_FREQ / (2400 * 2);
230 m_cass_data.wave_long = LX385_TAPE_SAMPLE_FREQ / (1200 * 2);
231 break;
232 case 0x02:
233 m_cass_data.speed = TAPE_600BPS;
234 m_cass_data.wave_filter = LX385_TAPE_SAMPLE_FREQ / 3200;
235 m_cass_data.wave_short = LX385_TAPE_SAMPLE_FREQ / (4800 * 2);
236 m_cass_data.wave_long = LX385_TAPE_SAMPLE_FREQ / (2400 * 2);
237 break;
238 case 0x04:
239 m_cass_data.speed = TAPE_1200BPS;
240 m_cass_data.wave_filter = LX385_TAPE_SAMPLE_FREQ / 6400;
241 m_cass_data.wave_short = LX385_TAPE_SAMPLE_FREQ / (9600 * 2);
242 m_cass_data.wave_long = LX385_TAPE_SAMPLE_FREQ / (4800 * 2);
243 }
244 m_cass_data.wave_length = m_cass_data.wave_short;
245 m_cass_data.output.length = m_cass_data.wave_length;
246 m_cass_data.output.level = 1;
247 m_cass_data.input.length = 0;
248 m_cass_data.input.bit = 1;
249
250 m_uart->write_cs(0);
251 m_uart->write_nb1(1);
252 m_uart->write_nb2(1);
253 m_uart->write_tsb(1);
254 m_uart->write_eps(1);
255 m_uart->write_np(m_io_lx_385->read() & 0x80 ? 1 : 0);
256 m_uart->write_cs(1);
257 m_uart_clock->set_unscaled_clock(m_cass_data.speed * 16);
258
259 lx385_ctrl_w(0);
260 }
261
machine_reset()262 void z80ne_state::machine_reset()
263 {
264 base_reset();
265
266 address_space &program = m_maincpu->space(AS_PROGRAM);
267 program.install_rom(0x0000, 0x03ff, m_rom); // do it here for F3
268 m_rom_shadow_tap = program.install_read_tap(0x8000, 0x83ff, "rom_shadow_r",[this](offs_t offset, u8 &data, u8 mem_mask)
269 {
270 if (!machine().side_effects_disabled())
271 {
272 // delete this tap
273 m_rom_shadow_tap->remove();
274
275 // reinstall ram over the rom shadow
276 m_maincpu->space(AS_PROGRAM).install_ram(0x0000, 0x03ff, m_mram);
277 }
278
279 // return the original data
280 return data;
281 });
282 }
283
machine_reset()284 void z80net_state::machine_reset()
285 {
286 reset_lx387();
287 z80ne_state::machine_reset();
288 }
289
machine_reset()290 void z80netb_state::machine_reset()
291 {
292 base_reset();
293 reset_lx387();
294 }
295
machine_reset()296 void z80netf_state::machine_reset()
297 {
298 reset_lx390_banking();
299 base_reset();
300 reset_lx387();
301
302 // basic roms are exempt from memory tap
303 if ((m_io_config->read() & 0x07) != 2)
304 {
305 address_space &program = m_maincpu->space(AS_PROGRAM);
306 m_rom_shadow_tap = program.install_read_tap(0x8000, 0xf3ff, "rom_shadow_r",[this](offs_t offset, u8 &data, u8 mem_mask)
307 {
308 if (!machine().side_effects_disabled())
309 {
310 // delete this tap
311 m_rom_shadow_tap->remove();
312
313 // reinstall ram over the rom shadow
314 m_bank1->set_entry(0);
315 }
316
317 // return the original data
318 return data;
319 });
320 }
321 }
322
INPUT_CHANGED_MEMBER(z80ne_state::z80ne_reset)323 INPUT_CHANGED_MEMBER(z80ne_state::z80ne_reset)
324 {
325 uint8_t rst = m_io_rst->read();
326
327 if ( ! BIT(rst, 0))
328 machine().schedule_soft_reset();
329 }
330
INPUT_CHANGED_MEMBER(z80net_state::z80net_nmi)331 INPUT_CHANGED_MEMBER(z80net_state::z80net_nmi)
332 {
333 uint8_t nmi = m_io_lx387_brk->read();
334
335 if ( ! BIT(nmi, 0))
336 m_maincpu->pulse_input_line(INPUT_LINE_NMI, attotime::zero);
337 }
338
machine_start()339 void z80ne_state::machine_start()
340 {
341 m_timer_nmi = timer_alloc(0);
342
343 m_lx383_digits.resolve();
344
345 m_lx385_ctrl = 0x1f;
346 m_cassette_timer = machine().scheduler().timer_alloc(timer_expired_delegate(FUNC(z80ne_state::z80ne_cassette_tc), this));
347 m_kbd_timer = machine().scheduler().timer_alloc(timer_expired_delegate(FUNC(z80ne_state::z80ne_kbd_scan), this));
348 m_kbd_timer->adjust(attotime::from_hz(1000), 0, attotime::from_hz(1000));
349 }
350
machine_start()351 void z80netf_state::machine_start()
352 {
353 z80ne_state::machine_start();
354 m_drv_led.resolve();
355 }
356
357 /******************************************************************************
358 Drivers
359 ******************************************************************************/
360
361 /* LX.383 - LX.384 HEX keyboard and display */
lx383_r()362 uint8_t z80ne_state::lx383_r()
363 {
364 /*
365 * Keyboard scanning
366 *
367 * IC14 NE555 astable oscillator
368 * IC13 74LS93 binary counter
369 * IC5 74LS240 tri-state buffer
370 *
371 * l'oscillatore NE555 alimenta il clock del contatore 74LS93
372 * D0 - Q(A) --\
373 * D1 - Q(B) |-- column
374 * D2 - Q(C) --/
375 * D3 - Q(D) row
376 * D4 - CTRL
377 * D5 - 0
378 * D6 - 0
379 * D7 - ~KEY Pressed
380 */
381 return m_lx383_key[m_lx383_scan_counter];
382 }
383
lx383_w(offs_t offset,uint8_t data)384 void z80ne_state::lx383_w(offs_t offset, uint8_t data)
385 {
386 /*
387 * First 8 locations (F0-F7) are mapped to a dual-port 8-byte RAM
388 * The 1KHz NE-555 astable oscillator circuit drive
389 * a 4-bit 74LS93 binary counter.
390 * The 3 least significant bits of the counter are connected
391 * both to the read address of the dual-port ram and to
392 * a 74LS156 3 to 8 binary decoder driving the cathode
393 * of 8 7-segments LEDS.
394 * The data output of the dual-port ram drive the anodes
395 * of the LEDS through 74LS07 buffers.
396 * LED segments - dual-port RAM bit:
397 * A 0x01
398 * B 0x02
399 * C 0x04
400 * D 0x08
401 * E 0x10
402 * F 0x20
403 * G 0x40
404 * P 0x80 (represented by DP in original schematics)
405 *
406 * A write in the range F0-FF starts a 74LS90 counter
407 * that trigger the NMI line of the CPU after 2 instruction
408 * fetch cycles for single step execution.
409 */
410
411 if ( offset < 8 )
412 m_lx383_digits[offset] = data ^ 0xff;
413 else
414 {
415 // after writing to port 0xF8 and the first ~M1 cycles strike a NMI for single step execution
416 m_timer_nmi->adjust(m_maincpu->cycles_to_attotime(1));
417 }
418 }
419
420
421 /* LX.385 Cassette tape interface */
422 /*
423 * NE555 is connected to a 74LS93 binary counter
424 * 74LS93 output:
425 * QA-QC: column index for LEDs and keyboard
426 * QD: keyboard row select
427 *
428 * Port EE: UART Data Read/Write
429 * Port EF: Status/Control
430 * read, UART status bits read
431 * 0 OR Overrun
432 * 1 FE Framing Error
433 * 2 PE Parity Error
434 * 3 TBMT Transmitter Buffer Empty
435 * 4 DAV Data Available
436 * 5 EOC End Of Character
437 * 6 1
438 * 7 1
439 * write, UART control bits / Tape Unit select / Modulation control
440 * 0 bit1=0, bit0=0 UART Reset pulse
441 * 1 bit1=0, bit0=1 UART RDAV (Reset Data Available) pulse
442 * 2 Tape modulation enable
443 * 3 *TAPEA Enable (active low) (at reset: low)
444 * 4 *TAPEB Enable (active low) (at reset: low)
445 * Cassette is connected to the uart data input and output via the cassette
446 * interface hardware.
447 *
448 * The cassette interface hardware converts square-wave pulses into bits which the uart receives.
449 *
450 * 1. the cassette format: "frequency shift" is converted
451 into the uart data format "non-return to zero"
452
453 2. on cassette a 1 data bit is stored as 8 2400 Hz pulses
454 and a 0 data bit as 4 1200 Hz pulses
455 - At 1200 baud, a logic 1 is 1 cycle of 1200 Hz and a logic 0 is 1/2 cycle of 600 Hz.
456 - At 300 baud, a logic 1 is 8 cycles of 2400 Hz and a logic 0 is 4 cycles of 1200 Hz.
457
458 Attenuation is applied to the signal and the square wave edges are rounded.
459
460 A manchester encoder is used. A flip-flop synchronises input
461 data on the positive-edge of the clock pulse.
462
463 The UART is a RCA CDP1854 CMOS device with pin 2 jumpered to GND to select the
464 AY-3-1015 compatibility mode. The jumper at P4 can be switched to place 12 V on
465 pin 2 for an old PMOS UART.
466 *
467 */
lx385_ctrl_r()468 uint8_t z80ne_state::lx385_ctrl_r()
469 {
470 /* set unused bits high */
471 uint8_t data = 0xc0;
472
473 m_uart->write_swe(0);
474 data |= (m_uart->or_r( ) ? 0x01 : 0);
475 data |= (m_uart->fe_r( ) ? 0x02 : 0);
476 data |= (m_uart->pe_r( ) ? 0x04 : 0);
477 data |= (m_uart->tbmt_r() ? 0x08 : 0);
478 data |= (m_uart->dav_r( ) ? 0x10 : 0);
479 data |= (m_uart->eoc_r( ) ? 0x20 : 0);
480 m_uart->write_swe(1);
481
482 return data;
483 }
484
485 #define LX385_CASSETTE_MOTOR_MASK ((1<<3)|(1<<4))
486
lx385_ctrl_w(uint8_t data)487 void z80ne_state::lx385_ctrl_w(uint8_t data)
488 {
489 /* Translate data to control signals
490 * 0 bit1=0, bit0=0 UART Reset pulse
491 * 1 bit1=0, bit0=1 UART RDAV (Reset Data Available) pulse
492 * 2 UART Tx Clock Enable (active high)
493 * 3 *TAPEA Enable (active low) (at reset: low)
494 * 4 *TAPEB Enable (active low) (at reset: low)
495 */
496 uint8_t uart_reset, uart_rdav;
497 uint8_t motor_a, motor_b;
498 uint8_t changed_bits = (m_lx385_ctrl ^ data) & 0x1C;
499 m_lx385_ctrl = data;
500
501 uart_reset = ((data & 0x03) == 0x00);
502 uart_rdav = ((data & 0x03) == 0x01);
503 motor_a = ((data & 0x08) == 0x00);
504 motor_b = ((data & 0x10) == 0x00);
505
506 /* UART Reset and RDAV */
507 if (uart_reset)
508 {
509 m_uart->write_xr(1);
510 m_uart->write_xr(0);
511 }
512
513 if (uart_rdav)
514 {
515 m_uart->write_rdav(1);
516 m_uart->write_rdav(0);
517 }
518
519 if (!changed_bits) return;
520
521 /* motors */
522 if(changed_bits & 0x18)
523 {
524 m_cassette1->change_state(
525 (motor_a) ? CASSETTE_MOTOR_ENABLED : CASSETTE_MOTOR_DISABLED,CASSETTE_MASK_MOTOR);
526
527 m_cassette2->change_state(
528 (motor_b) ? CASSETTE_MOTOR_ENABLED : CASSETTE_MOTOR_DISABLED,CASSETTE_MASK_MOTOR);
529
530 if (motor_a || motor_b)
531 m_cassette_timer->adjust(attotime::zero, 0, attotime::from_hz(LX385_TAPE_SAMPLE_FREQ));
532 else
533 m_cassette_timer->adjust(attotime::zero);
534 }
535 }
536
WRITE_LINE_MEMBER(z80ne_state::lx385_uart_tx_clock_w)537 WRITE_LINE_MEMBER(z80ne_state::lx385_uart_tx_clock_w)
538 {
539 if (BIT(m_lx385_ctrl, 2))
540 m_uart->write_tcp(state);
541 }
542
READ_LINE_MEMBER(z80net_state::lx387_shift_r)543 READ_LINE_MEMBER(z80net_state::lx387_shift_r)
544 {
545 return BIT(m_io_modifiers->read(), 0) || BIT(m_io_modifiers->read(), 2);
546 }
547
READ_LINE_MEMBER(z80net_state::lx387_control_r)548 READ_LINE_MEMBER(z80net_state::lx387_control_r)
549 {
550 return BIT(m_io_modifiers->read(), 1);
551 }
552
lx388_mc6847_videoram_r(offs_t offset)553 uint8_t z80net_state::lx388_mc6847_videoram_r(offs_t offset)
554 {
555 if (offset == ~0) return 0xff;
556
557 int d6 = BIT(m_videoram[offset], 6);
558 int d7 = BIT(m_videoram[offset], 7);
559
560 m_vdg->inv_w(d6 && d7);
561 m_vdg->as_w(!d6 && d7);
562 m_vdg->intext_w(!d6 && d7);
563
564 return m_videoram[offset];
565 }
566
lx387_data_r()567 uint8_t z80net_state::lx387_data_r()
568 {
569 uint8_t data = m_lx387_kr2376->data_r() & 0x7f;
570 data |= m_lx387_kr2376->get_output_pin(kr2376_device::KR2376_SO) << 7;
571 return data;
572 }
573
lx388_read_field_sync()574 uint8_t z80net_state::lx388_read_field_sync()
575 {
576 return m_vdg->fs_r() << 7;
577 }
578
579 /*
580 * DRQ INTRQ IC9B.10 IC8B.*Q
581 * 0 0 1 0
582 * 0 1 0 x
583 * 1 0 0 x
584 * 1 1 0 x
585 *
586 */
587
lx390_motor_w(uint8_t data)588 void z80netf_state::lx390_motor_w(uint8_t data)
589 {
590 /* Selection of drive and parameters
591 A write also causes the selected drive motor to turn on for about 3 seconds.
592 When the motor turns off, the drive is deselected.
593 d7 Unused (trs80: 1=MFM, 0=FM)
594 d6 (trs80: 1=Wait)
595 d5 0=Side 0, 1=Side 1 (trs80: 1=Write Precompensation enabled)
596 d4 Unused (trs80: 0=Side 0, 1=Side 1)
597 d3 1=select drive 3
598 d2 1=select drive 2
599 d1 1=select drive 1
600 d0 1=select drive 0 */
601
602 floppy_image_device *floppy = nullptr;
603
604 for (u8 f = 0; f < 4; f++)
605 if (BIT(data, f))
606 floppy = m_floppy[f]->get_device();
607
608 m_wd1771->set_floppy(floppy);
609
610 if (floppy)
611 {
612 floppy->ss_w(BIT(data, 5));
613 floppy->mon_w(0);
614 }
615
616 m_wd17xx_state.head = (data & 32) ? 1 : 0;
617 m_wd17xx_state.drive = data & 0x0F;
618
619 /* no drive selected, turn off all leds */
620 if (!m_wd17xx_state.drive)
621 {
622 m_drv_led[0] = 0;
623 m_drv_led[1] = 0;
624 }
625 }
626
lx390_fdc_r(offs_t offset)627 uint8_t z80netf_state::lx390_fdc_r(offs_t offset)
628 {
629 uint8_t d;
630
631 switch(offset)
632 {
633 case 0:
634 d = m_wd1771->status_r() ^ 0xff;
635 LOG("lx390_fdc_r, WD17xx status: %02x\n", d);
636 break;
637 case 1:
638 d = m_wd1771->track_r() ^ 0xff;
639 LOG("lx390_fdc_r, WD17xx track: %02x\n", d);
640 break;
641 case 2:
642 d = m_wd1771->sector_r() ^ 0xff;
643 LOG("lx390_fdc_r, WD17xx sector: %02x\n", d);
644 break;
645 case 3:
646 d = m_wd1771->data_r() ^ 0xff;
647 LOG("lx390_fdc_r, WD17xx data3: %02x\n", d);
648 break;
649 case 6:
650 d = 0xff;
651 m_bank1->set_entry(0);
652 break;
653 case 7:
654 d = m_wd1771->data_r() ^ 0xff;
655 LOG("lx390_fdc_r, WD17xx data7, force: %02x\n", d);
656 break;
657 default:
658 d = 0x00;
659 }
660 return d;
661 }
662
lx390_fdc_w(offs_t offset,uint8_t data)663 void z80netf_state::lx390_fdc_w(offs_t offset, uint8_t data)
664 {
665 uint8_t d = data;
666 switch(offset)
667 {
668 case 0:
669 LOG("lx390_fdc_w, WD17xx command: %02x\n", d);
670 m_wd1771->cmd_w(d ^ 0xff);
671 if (m_wd17xx_state.drive & 1)
672 m_drv_led[0] = 2;
673 else if (m_wd17xx_state.drive & 2)
674 m_drv_led[1] = 2;
675 break;
676 case 1:
677 LOG("lx390_fdc_w, WD17xx track: %02x\n", d);
678 m_wd1771->track_w(d ^ 0xff);
679 break;
680 case 2:
681 LOG("lx390_fdc_w, WD17xx sector: %02x\n", d);
682 m_wd1771->sector_w(d ^ 0xff);
683 break;
684 case 3:
685 m_wd1771->data_w(d ^ 0xff);
686 LOG("lx390_fdc_w, WD17xx data3: %02x\n", d);
687 break;
688 case 6:
689 LOG("lx390_fdc_w, motor_w: %02x\n", d);
690 lx390_motor_w(d);
691 break;
692 case 7:
693 LOG("lx390_fdc_w, WD17xx data7, force: %02x\n", d);
694 m_wd1771->data_w(d ^ 0xff);
695 break;
696 }
697 }
698