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