1 // license:BSD-3-Clause
2 // copyright-holders:Aaron Giles
3 /***************************************************************************
4 
5     williams.h
6 
7     Functions to emulate general the various Williams/Midway sound cards.
8 
9 ****************************************************************************
10 
11     Midway/Williams Audio Boards
12     ----------------------------
13 
14     6809 MEMORY MAP
15 
16     Function                                  Address     R/W  Data
17     ---------------------------------------------------------------
18     Program RAM                               0000-07FF   R/W  D0-D7
19 
20     Music (YM-2151)                           2000-2001   R/W  D0-D7
21 
22     6821 PIA                                  4000-4003   R/W  D0-D7
23 
24     HC55516 clock low, digit latch            6000        W    D0
25     HC55516 clock high                        6800        W    xx
26 
27     Bank select                               7800        W    D0-D2
28 
29     Banked Program ROM                        8000-FFFF   R    D0-D7
30 
31 ****************************************************************************/
32 
33 #include "emu.h"
34 #include "williams.h"
35 #include "machine/6821pia.h"
36 #include "machine/rescap.h"
37 #include "cpu/m6809/m6809.h"
38 #include "sound/ym2151.h"
39 #include "sound/okim6295.h"
40 #include "sound/hc55516.h"
41 #include "sound/dac.h"
42 
43 
44 #define NARC_MASTER_CLOCK       XTAL(8'000'000)
45 #define NARC_FM_CLOCK           XTAL(3'579'545)
46 
47 #define CVSD_MASTER_CLOCK       XTAL(8'000'000)
48 #define CVSD_FM_CLOCK           XTAL(3'579'545)
49 
50 #define ADPCM_MASTER_CLOCK      XTAL(8'000'000)
51 #define ADPCM_FM_CLOCK          XTAL(3'579'545)
52 
53 
54 
55 //**************************************************************************
56 //  GLOBAL VARIABLES
57 //**************************************************************************
58 
59 DEFINE_DEVICE_TYPE(WILLIAMS_CVSD_SOUND, williams_cvsd_sound_device, "wmscvsd", "Williams CVSD Sound Board")
60 DEFINE_DEVICE_TYPE(WILLIAMS_NARC_SOUND, williams_narc_sound_device, "wmsnarc", "Williams NARC Sound Board")
61 DEFINE_DEVICE_TYPE(WILLIAMS_ADPCM_SOUND, williams_adpcm_sound_device, "wmsadpcm", "Williams ADPCM Sound Board")
62 
63 
64 
65 //**************************************************************************
66 //  CVSD SOUND BOARD
67 //**************************************************************************
68 
69 //-------------------------------------------------
70 //  williams_cvsd_sound_device - constructor
71 //-------------------------------------------------
72 
williams_cvsd_sound_device(const machine_config & mconfig,const char * tag,device_t * owner,u32 clock)73 williams_cvsd_sound_device::williams_cvsd_sound_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock)
74 	: device_t(mconfig, WILLIAMS_CVSD_SOUND, tag, owner, clock),
75 		device_mixer_interface(mconfig, *this),
76 		m_cpu(*this, "cpu"),
77 		m_pia(*this, "pia"),
78 		m_ym2151(*this, "ym2151"),
79 		m_hc55516(*this, "cvsd"),
80 		m_rombank(*this, "rombank"),
81 		m_talkback(0)
82 {
83 }
84 
85 
86 //-------------------------------------------------
87 //  write - handle an external write to the input
88 //  latch
89 //-------------------------------------------------
90 
write(u16 data)91 void williams_cvsd_sound_device::write(u16 data)
92 {
93 	synchronize(0, data);
94 }
95 
96 
97 //-------------------------------------------------
98 //  reset_write - write to the reset line
99 //-------------------------------------------------
100 
WRITE_LINE_MEMBER(williams_cvsd_sound_device::reset_write)101 WRITE_LINE_MEMBER(williams_cvsd_sound_device::reset_write)
102 {
103 	// going high halts the CPU
104 	if (state)
105 	{
106 		bank_select_w(0);
107 		device_reset();
108 		m_cpu->set_input_line(INPUT_LINE_RESET, ASSERT_LINE);
109 	}
110 
111 	// going low resets and reactivates the CPU
112 	else
113 		m_cpu->set_input_line(INPUT_LINE_RESET, CLEAR_LINE);
114 }
115 
116 
117 //-------------------------------------------------
118 //  bank_select_w - change memory banks
119 //-------------------------------------------------
120 
bank_select_w(u8 data)121 void williams_cvsd_sound_device::bank_select_w(u8 data)
122 {
123 	m_rombank->set_entry(data & 0x0f);
124 }
125 
126 
127 //-------------------------------------------------
128 //  talkback_w - write to the talkback latch
129 //-------------------------------------------------
130 
talkback_w(u8 data)131 void williams_cvsd_sound_device::talkback_w(u8 data)
132 {
133 	m_talkback = data;
134 	logerror("CVSD Talkback = %02X\n", data);
135 }
136 
137 
138 //-------------------------------------------------
139 //  cvsd_digit_clock_clear_w - clear the clock on
140 //  the HC55516 and clock the data
141 //-------------------------------------------------
142 
cvsd_digit_clock_clear_w(u8 data)143 void williams_cvsd_sound_device::cvsd_digit_clock_clear_w(u8 data)
144 {
145 	m_hc55516->clock_w(0);
146 	m_hc55516->digit_w(data&1);
147 }
148 
149 
150 //-------------------------------------------------
151 //  cvsd_clock_set_w - set the clock on the HC55516
152 //-------------------------------------------------
153 
cvsd_clock_set_w(u8 data)154 void williams_cvsd_sound_device::cvsd_clock_set_w(u8 data)
155 {
156 	m_hc55516->clock_w(1);
157 }
158 
159 
160 //-------------------------------------------------
161 //  audio CPU map
162 //-------------------------------------------------
163 
williams_cvsd_map(address_map & map)164 void williams_cvsd_sound_device::williams_cvsd_map(address_map &map)
165 {
166 	map(0x0000, 0x07ff).mirror(0x1800).ram();
167 	map(0x2000, 0x2001).mirror(0x1ffe).rw("ym2151", FUNC(ym2151_device::read), FUNC(ym2151_device::write));
168 	map(0x4000, 0x4003).mirror(0x1ffc).rw("pia", FUNC(pia6821_device::read), FUNC(pia6821_device::write));
169 	map(0x6000, 0x6000).mirror(0x07ff).w(FUNC(williams_cvsd_sound_device::cvsd_digit_clock_clear_w));
170 	map(0x6800, 0x6800).mirror(0x07ff).w(FUNC(williams_cvsd_sound_device::cvsd_clock_set_w));
171 	map(0x7800, 0x7800).mirror(0x07ff).w(FUNC(williams_cvsd_sound_device::bank_select_w));
172 	map(0x8000, 0xffff).bankr("rombank");
173 }
174 
175 
176 //-------------------------------------------------
177 // device_add_mconfig - add device configuration
178 //-------------------------------------------------
179 
device_add_mconfig(machine_config & config)180 void williams_cvsd_sound_device::device_add_mconfig(machine_config &config)
181 {
182 	MC6809E(config, m_cpu, CVSD_MASTER_CLOCK / 4);
183 	m_cpu->set_addrmap(AS_PROGRAM, &williams_cvsd_sound_device::williams_cvsd_map);
184 
185 	PIA6821(config, m_pia, 0);
186 	m_pia->writepa_handler().set("dac", FUNC(dac_byte_interface::data_w));
187 	m_pia->writepb_handler().set(FUNC(williams_cvsd_sound_device::talkback_w));
188 	m_pia->ca2_handler().set(m_ym2151, FUNC(ym2151_device::reset_w));
189 	m_pia->irqa_handler().set_inputline(m_cpu, M6809_FIRQ_LINE);
190 	m_pia->irqb_handler().set_inputline(m_cpu, INPUT_LINE_NMI);
191 
192 	YM2151(config, m_ym2151, CVSD_FM_CLOCK);
193 	m_ym2151->irq_handler().set(m_pia, FUNC(pia6821_device::ca1_w)).invert(); // IRQ is not true state
194 	m_ym2151->add_route(ALL_OUTPUTS, *this, 0.10);
195 
196 	MC1408(config, "dac", 0).add_route(ALL_OUTPUTS, *this, 0.25);
197 
198 	HC55516(config, m_hc55516, 0);
199 	m_hc55516->add_route(ALL_OUTPUTS, *this, 0.60);
200 }
201 
202 
203 //-------------------------------------------------
204 //  device_start - device-specific startup
205 //-------------------------------------------------
206 
device_start()207 void williams_cvsd_sound_device::device_start()
208 {
209 	// configure master CPU banks
210 	u8 *rom = memregion("cpu")->base();
211 	for (int bank = 0; bank < 16; bank++)
212 	{
213 		//
214 		//  D0/D1 -> selects: 0=U4 1=U19 2=U20 3=n/c
215 		//  D2 -> A15
216 		//  D3 -> A16
217 		//
218 		offs_t offset = 0x8000 * ((bank >> 2) & 3) + 0x20000 * (bank & 3);
219 		m_rombank->configure_entry(bank, &rom[0x10000 + offset]);
220 	}
221 	m_rombank->set_entry(0);
222 
223 	// reset the IRQ state
224 	m_pia->ca1_w(1);
225 
226 	// register for save states
227 	save_item(NAME(m_talkback));
228 }
229 
230 
231 //-------------------------------------------------
232 //  device_reset - device-specific reset
233 //-------------------------------------------------
234 
device_reset()235 void williams_cvsd_sound_device::device_reset()
236 {
237 	// reset interrupt states
238 	m_cpu->set_input_line(M6809_FIRQ_LINE, CLEAR_LINE);
239 	m_cpu->set_input_line(M6809_IRQ_LINE, CLEAR_LINE);
240 	m_cpu->set_input_line(INPUT_LINE_NMI, CLEAR_LINE);
241 }
242 
243 
244 //-------------------------------------------------
245 //  device_timer - timer callbacks
246 //-------------------------------------------------
247 
device_timer(emu_timer & timer,device_timer_id id,int param,void * ptr)248 void williams_cvsd_sound_device::device_timer(emu_timer &timer, device_timer_id id, int param, void *ptr)
249 {
250 	// process incoming data write
251 	m_pia->portb_w(param & 0xff);
252 	m_pia->cb1_w((param >> 8) & 1);
253 	m_pia->cb2_w((param >> 9) & 1);
254 }
255 
256 
257 
258 //**************************************************************************
259 //  NARC SOUND BOARD
260 //**************************************************************************
261 
262 //-------------------------------------------------
263 //  williams_narc_sound_device - constructor
264 //-------------------------------------------------
265 
williams_narc_sound_device(const machine_config & mconfig,const char * tag,device_t * owner,u32 clock)266 williams_narc_sound_device::williams_narc_sound_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock)
267 	: device_t(mconfig, WILLIAMS_NARC_SOUND, tag, owner, clock),
268 		device_mixer_interface(mconfig, *this),
269 		m_cpu(*this, "cpu%u", 0U),
270 		m_hc55516(*this, "cvsd"),
271 		m_masterbank(*this, "masterbank"),
272 		m_slavebank(*this, "slavebank"),
273 		m_latch(0),
274 		m_latch2(0),
275 		m_talkback(0),
276 		m_audio_sync(0),
277 		m_sound_int_state(0)
278 {
279 }
280 
281 
282 //-------------------------------------------------
283 //  read - return the talkback register with the
284 //  SYNC bits in bits 8 and 9
285 //-------------------------------------------------
286 
read()287 u16 williams_narc_sound_device::read()
288 {
289 	return m_talkback | (m_audio_sync << 8);
290 }
291 
292 
293 //-------------------------------------------------
294 //  write - handle an external write to the input
295 //  latch
296 //-------------------------------------------------
297 
write(u16 data)298 void williams_narc_sound_device::write(u16 data)
299 {
300 	synchronize(TID_MASTER_COMMAND, data);
301 }
302 
303 
304 //-------------------------------------------------
305 //  reset_write - write to the reset line
306 //-------------------------------------------------
307 
WRITE_LINE_MEMBER(williams_narc_sound_device::reset_write)308 WRITE_LINE_MEMBER(williams_narc_sound_device::reset_write)
309 {
310 	// going high halts the CPU
311 	if (state)
312 	{
313 		master_bank_select_w(0);
314 		slave_bank_select_w(0);
315 		device_reset();
316 		m_cpu[0]->set_input_line(INPUT_LINE_RESET, ASSERT_LINE);
317 		m_cpu[1]->set_input_line(INPUT_LINE_RESET, ASSERT_LINE);
318 	}
319 
320 	// going low resets and reactivates the CPU
321 	else
322 	{
323 		m_cpu[0]->set_input_line(INPUT_LINE_RESET, CLEAR_LINE);
324 		m_cpu[1]->set_input_line(INPUT_LINE_RESET, CLEAR_LINE);
325 	}
326 }
327 
328 
329 //-------------------------------------------------
330 //  master_bank_select_w - select the bank for the
331 //  master CPU
332 //-------------------------------------------------
333 
master_bank_select_w(u8 data)334 void williams_narc_sound_device::master_bank_select_w(u8 data)
335 {
336 	m_masterbank->set_entry(data & 0x0f);
337 }
338 
339 
340 //-------------------------------------------------
341 //  slave_bank_select_w - select the bank for the
342 //  slave CPU
343 //-------------------------------------------------
344 
slave_bank_select_w(u8 data)345 void williams_narc_sound_device::slave_bank_select_w(u8 data)
346 {
347 	m_slavebank->set_entry(data & 0x0f);
348 }
349 
350 
351 //-------------------------------------------------
352 //  command_r - read command written by external
353 //  agent
354 //-------------------------------------------------
355 
command_r()356 u8 williams_narc_sound_device::command_r()
357 {
358 	m_cpu[0]->set_input_line(M6809_IRQ_LINE, CLEAR_LINE);
359 	m_sound_int_state = 0;
360 	return m_latch;
361 }
362 
363 
364 //-------------------------------------------------
365 //  command2_w - write command from master CPU to
366 //  slave CPU
367 //-------------------------------------------------
368 
command2_w(u8 data)369 void williams_narc_sound_device::command2_w(u8 data)
370 {
371 	synchronize(TID_SLAVE_COMMAND, data);
372 }
373 
374 
375 //-------------------------------------------------
376 //  command2_r - read command written by master
377 //  CPU
378 //-------------------------------------------------
379 
command2_r()380 u8 williams_narc_sound_device::command2_r()
381 {
382 	m_cpu[1]->set_input_line(M6809_FIRQ_LINE, CLEAR_LINE);
383 	return m_latch2;
384 }
385 
386 
387 //-------------------------------------------------
388 //  master_talkback_w - handle writes to the
389 //  talkback latch from the master CPU
390 //-------------------------------------------------
391 
master_talkback_w(u8 data)392 void williams_narc_sound_device::master_talkback_w(u8 data)
393 {
394 	m_talkback = data;
395 	logerror("Master Talkback = %02X\n", data);
396 }
397 
398 
399 //-------------------------------------------------
400 //  master_sync_w - handle writes to the master
401 //  SYNC register
402 //-------------------------------------------------
403 
master_sync_w(u8 data)404 void williams_narc_sound_device::master_sync_w(u8 data)
405 {
406 	timer_set(attotime::from_double(TIME_OF_74LS123(180000, 0.000001)), TID_SYNC_CLEAR, 0x01);
407 	m_audio_sync |= 0x01;
408 	logerror("Master sync = %02X\n", data);
409 }
410 
411 
412 //-------------------------------------------------
413 //  slave_talkback_w - handle writes to the
414 //  talkback latch from the slave CPU
415 //-------------------------------------------------
416 
slave_talkback_w(u8 data)417 void williams_narc_sound_device::slave_talkback_w(u8 data)
418 {
419 	logerror("Slave Talkback = %02X\n", data);
420 }
421 
422 
423 //-------------------------------------------------
424 //  slave_sync_w - handle writes to the slave
425 //  SYNC register
426 //-------------------------------------------------
427 
slave_sync_w(u8 data)428 void williams_narc_sound_device::slave_sync_w(u8 data)
429 {
430 	timer_set(attotime::from_double(TIME_OF_74LS123(180000, 0.000001)), TID_SYNC_CLEAR, 0x02);
431 	m_audio_sync |= 0x02;
432 	logerror("Slave sync = %02X\n", data);
433 }
434 
435 
436 //-------------------------------------------------
437 //  cvsd_digit_clock_clear_w - clear the clk pin on
438 //  the HC555xx and clock the data latch
439 //-------------------------------------------------
440 
cvsd_digit_clock_clear_w(u8 data)441 void williams_narc_sound_device::cvsd_digit_clock_clear_w(u8 data)
442 {
443 	m_hc55516->clock_w(0);
444 	m_hc55516->digit_w(data&1);
445 }
446 
447 
448 //---------------------------------------------------
449 //  cvsd_clock_set_w - set the clk pin on the HC555xx
450 //---------------------------------------------------
451 
cvsd_clock_set_w(u8 data)452 void williams_narc_sound_device::cvsd_clock_set_w(u8 data)
453 {
454 	m_hc55516->clock_w(1);
455 }
456 
457 
458 //-------------------------------------------------
459 //  master CPU map
460 //-------------------------------------------------
461 
williams_narc_master_map(address_map & map)462 void williams_narc_sound_device::williams_narc_master_map(address_map &map)
463 {
464 	map(0x0000, 0x1fff).ram();
465 	map(0x2000, 0x2001).mirror(0x03fe).rw("ym2151", FUNC(ym2151_device::read), FUNC(ym2151_device::write));
466 	map(0x2800, 0x2800).mirror(0x03ff).w(FUNC(williams_narc_sound_device::master_talkback_w));
467 	map(0x2c00, 0x2c00).mirror(0x03ff).w(FUNC(williams_narc_sound_device::command2_w));
468 	map(0x3000, 0x3000).mirror(0x03ff).w("dac1", FUNC(dac_byte_interface::data_w));
469 	map(0x3400, 0x3400).mirror(0x03ff).r(FUNC(williams_narc_sound_device::command_r));
470 	map(0x3800, 0x3800).mirror(0x03ff).w(FUNC(williams_narc_sound_device::master_bank_select_w));
471 	map(0x3c00, 0x3c00).mirror(0x03ff).w(FUNC(williams_narc_sound_device::master_sync_w));
472 	map(0x4000, 0xbfff).bankr("masterbank");
473 	map(0xc000, 0xffff).bankr("masterupper");
474 }
475 
476 
477 //-------------------------------------------------
478 //  slave CPU map
479 //-------------------------------------------------
480 
williams_narc_slave_map(address_map & map)481 void williams_narc_sound_device::williams_narc_slave_map(address_map &map)
482 {
483 	map(0x0000, 0x1fff).ram();
484 	map(0x2000, 0x2000).mirror(0x03ff).w(FUNC(williams_narc_sound_device::cvsd_clock_set_w));
485 	map(0x2400, 0x2400).mirror(0x03ff).w(FUNC(williams_narc_sound_device::cvsd_digit_clock_clear_w));
486 	map(0x2800, 0x2800).mirror(0x03ff).w(FUNC(williams_narc_sound_device::slave_talkback_w));
487 	map(0x3000, 0x3000).mirror(0x03ff).w("dac2", FUNC(dac_byte_interface::data_w));
488 	map(0x3400, 0x3400).mirror(0x03ff).r(FUNC(williams_narc_sound_device::command2_r));
489 	map(0x3800, 0x3800).mirror(0x03ff).w(FUNC(williams_narc_sound_device::slave_bank_select_w));
490 	map(0x3c00, 0x3c00).mirror(0x03ff).w(FUNC(williams_narc_sound_device::slave_sync_w));
491 	map(0x4000, 0xbfff).bankr("slavebank");
492 	map(0xc000, 0xffff).bankr("slaveupper");
493 }
494 
495 
496 //-------------------------------------------------
497 // device_add_mconfig - add device configuration
498 //-------------------------------------------------
499 
500 
device_add_mconfig(machine_config & config)501 void williams_narc_sound_device::device_add_mconfig(machine_config &config)
502 {
503 	MC6809E(config, m_cpu[0], NARC_MASTER_CLOCK / 4);
504 	m_cpu[0]->set_addrmap(AS_PROGRAM, &williams_narc_sound_device::williams_narc_master_map);
505 
506 	MC6809E(config, m_cpu[1], NARC_MASTER_CLOCK / 4);
507 	m_cpu[1]->set_addrmap(AS_PROGRAM, &williams_narc_sound_device::williams_narc_slave_map);
508 
509 	ym2151_device &ym2151(YM2151(config, "ym2151", NARC_FM_CLOCK));
510 	ym2151.irq_handler().set_inputline("cpu0", M6809_FIRQ_LINE);
511 	ym2151.add_route(ALL_OUTPUTS, *this, 0.10);
512 
513 	AD7224(config, "dac1", 0).add_route(ALL_OUTPUTS, *this, 0.25);
514 	AD7224(config, "dac2", 0).add_route(ALL_OUTPUTS, *this, 0.25);
515 
516 	HC55516(config, m_hc55516, 0).add_route(ALL_OUTPUTS, *this, 0.60);
517 }
518 
519 
520 //-------------------------------------------------
521 //  device_start - device-specific startup
522 //-------------------------------------------------
523 
device_start()524 void williams_narc_sound_device::device_start()
525 {
526 	// configure master CPU banks
527 	u8 *rom = memregion("cpu0")->base();
528 	for (int bank = 0; bank < 16; bank++)
529 	{
530 		//
531 		//  D0 -> A15
532 		//  D1/D2 -> selects: 0=n/c 1=U3 2=U4 3=U5
533 		//  D3 -> A16
534 		//
535 		offs_t offset = 0x8000 * (bank & 1) + 0x10000 * ((bank >> 3) & 1) + 0x20000 * ((bank >> 1) & 3);
536 		m_masterbank->configure_entry(bank, &rom[0x10000 + offset]);
537 	}
538 	membank("masterupper")->set_base(&rom[0x10000 + 0x4000 + 0x8000 + 0x10000 + 0x20000 * 3]);
539 
540 	// configure slave CPU banks
541 	rom = memregion("cpu1")->base();
542 	for (int bank = 0; bank < 16; bank++)
543 	{
544 		//
545 		//  D0 -> A15
546 		//  D1/D2 -> selects: 0=U35 1=U36 2=U37 3=U38
547 		//  D3 -> A16
548 		//
549 		offs_t offset = 0x8000 * (bank & 1) + 0x10000 * ((bank >> 3) & 1) + 0x20000 * ((bank >> 1) & 3);
550 		m_slavebank->configure_entry(bank, &rom[0x10000 + offset]);
551 	}
552 	membank("slaveupper")->set_base(&rom[0x10000 + 0x4000 + 0x8000 + 0x10000 + 0x20000 * 3]);
553 
554 	// register for save states
555 	save_item(NAME(m_latch));
556 	save_item(NAME(m_latch2));
557 	save_item(NAME(m_talkback));
558 	save_item(NAME(m_audio_sync));
559 	save_item(NAME(m_sound_int_state));
560 }
561 
562 
563 //-------------------------------------------------
564 //  device_reset - device-specific reset
565 //-------------------------------------------------
566 
device_reset()567 void williams_narc_sound_device::device_reset()
568 {
569 	// reset interrupt states
570 	m_sound_int_state = 0;
571 	m_cpu[0]->set_input_line(M6809_FIRQ_LINE, CLEAR_LINE);
572 	m_cpu[0]->set_input_line(M6809_IRQ_LINE, CLEAR_LINE);
573 	m_cpu[0]->set_input_line(INPUT_LINE_NMI, CLEAR_LINE);
574 	m_cpu[1]->set_input_line(M6809_FIRQ_LINE, CLEAR_LINE);
575 	m_cpu[1]->set_input_line(M6809_IRQ_LINE, CLEAR_LINE);
576 	m_cpu[1]->set_input_line(INPUT_LINE_NMI, CLEAR_LINE);
577 }
578 
579 
580 //-------------------------------------------------
581 //  device_timer - timer callbacks
582 //-------------------------------------------------
583 
device_timer(emu_timer & timer,device_timer_id id,int param,void * ptr)584 void williams_narc_sound_device::device_timer(emu_timer &timer, device_timer_id id, int param, void *ptr)
585 {
586 	switch (id)
587 	{
588 		case TID_MASTER_COMMAND:
589 			m_latch = param & 0xff;
590 			m_cpu[0]->set_input_line(INPUT_LINE_NMI, (param & 0x100) ? CLEAR_LINE : ASSERT_LINE);
591 			if ((param & 0x200) == 0)
592 			{
593 				m_cpu[0]->set_input_line(M6809_IRQ_LINE, ASSERT_LINE);
594 				m_sound_int_state = 1;
595 			}
596 			break;
597 
598 		case TID_SLAVE_COMMAND:
599 			m_latch2 = param & 0xff;
600 			m_cpu[1]->set_input_line(M6809_FIRQ_LINE, ASSERT_LINE);
601 			break;
602 
603 		case TID_SYNC_CLEAR:
604 			m_audio_sync &= ~param;
605 			break;
606 	}
607 }
608 
609 
610 //**************************************************************************
611 //  ADPCM SOUND BOARD
612 //**************************************************************************
613 
614 //-------------------------------------------------
615 //  williams_adpcm_sound_device - constructor
616 //-------------------------------------------------
617 
williams_adpcm_sound_device(const machine_config & mconfig,const char * tag,device_t * owner,u32 clock)618 williams_adpcm_sound_device::williams_adpcm_sound_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock)
619 	: device_t(mconfig, WILLIAMS_ADPCM_SOUND, tag, owner, clock),
620 		device_mixer_interface(mconfig, *this),
621 		m_cpu(*this, "cpu"),
622 		m_rombank(*this, "rombank"),
623 		m_okibank(*this, "okibank"),
624 		m_latch(0),
625 		m_talkback(0),
626 		m_sound_int_state(0)
627 {
628 }
629 
630 
631 //-------------------------------------------------
632 //  write - handle an external write to the input
633 //  latch
634 //-------------------------------------------------
635 
write(u16 data)636 void williams_adpcm_sound_device::write(u16 data)
637 {
638 	synchronize(TID_COMMAND, data);
639 }
640 
641 
642 //-------------------------------------------------
643 //  reset_write - write to the reset line
644 //-------------------------------------------------
645 
WRITE_LINE_MEMBER(williams_adpcm_sound_device::reset_write)646 WRITE_LINE_MEMBER(williams_adpcm_sound_device::reset_write)
647 {
648 	// going high halts the CPU
649 	if (state)
650 	{
651 		bank_select_w(0);
652 		device_reset();
653 		m_cpu->set_input_line(INPUT_LINE_RESET, ASSERT_LINE);
654 	}
655 
656 	// going low resets and reactivates the CPU
657 	else
658 		m_cpu->set_input_line(INPUT_LINE_RESET, CLEAR_LINE);
659 }
660 
661 
662 //-------------------------------------------------
663 //  irq_read - read the sound IRQ state
664 //-------------------------------------------------
665 
READ_LINE_MEMBER(williams_adpcm_sound_device::irq_read)666 READ_LINE_MEMBER(williams_adpcm_sound_device::irq_read)
667 {
668 	return m_sound_int_state;
669 }
670 
671 
672 //-------------------------------------------------
673 //  bank_select_w - select the sound CPU memory
674 //  bank
675 //-------------------------------------------------
676 
bank_select_w(u8 data)677 void williams_adpcm_sound_device::bank_select_w(u8 data)
678 {
679 	m_rombank->set_entry(data & 0x07);
680 }
681 
682 
683 //-------------------------------------------------
684 //  oki6295_bank_select_w - select the OKI6295
685 //  memory bank
686 //-------------------------------------------------
687 
oki6295_bank_select_w(u8 data)688 void williams_adpcm_sound_device::oki6295_bank_select_w(u8 data)
689 {
690 	m_okibank->set_entry(data & 7);
691 }
692 
693 
694 //-------------------------------------------------
695 //  command_r - read the command from the external
696 //  latch
697 //-------------------------------------------------
698 
command_r()699 u8 williams_adpcm_sound_device::command_r()
700 {
701 	m_cpu->set_input_line(M6809_IRQ_LINE, CLEAR_LINE);
702 
703 	// don't clear the external IRQ state for a short while; this allows the
704 	// self-tests to pass
705 	timer_set(attotime::from_usec(10), TID_IRQ_CLEAR);
706 	return m_latch;
707 }
708 
709 
710 //-------------------------------------------------
711 //  talkback_w - write to the talkback latch
712 //-------------------------------------------------
713 
talkback_w(u8 data)714 void williams_adpcm_sound_device::talkback_w(u8 data)
715 {
716 	m_talkback = data;
717 	logerror("ADPCM Talkback = %02X\n", data);
718 }
719 
720 
721 //-------------------------------------------------
722 //  audio CPU map
723 //-------------------------------------------------
724 
williams_adpcm_map(address_map & map)725 void williams_adpcm_sound_device::williams_adpcm_map(address_map &map)
726 {
727 	map(0x0000, 0x1fff).ram();
728 	map(0x2000, 0x2000).mirror(0x03ff).w(FUNC(williams_adpcm_sound_device::bank_select_w));
729 	map(0x2400, 0x2401).mirror(0x03fe).rw("ym2151", FUNC(ym2151_device::read), FUNC(ym2151_device::write));
730 	map(0x2800, 0x2800).mirror(0x03ff).w("dac", FUNC(dac_byte_interface::data_w));
731 	map(0x2c00, 0x2c00).mirror(0x03ff).rw("oki", FUNC(okim6295_device::read), FUNC(okim6295_device::write));
732 	map(0x3000, 0x3000).mirror(0x03ff).r(FUNC(williams_adpcm_sound_device::command_r));
733 	map(0x3400, 0x3400).mirror(0x03ff).w(FUNC(williams_adpcm_sound_device::oki6295_bank_select_w));
734 	map(0x3c00, 0x3c00).mirror(0x03ff).w(FUNC(williams_adpcm_sound_device::talkback_w));
735 	map(0x4000, 0xbfff).bankr("rombank");
736 	map(0xc000, 0xffff).bankr("romupper");
737 }
738 
739 
740 //-------------------------------------------------
741 //  OKI6295 map
742 //-------------------------------------------------
743 
williams_adpcm_oki_map(address_map & map)744 void williams_adpcm_sound_device::williams_adpcm_oki_map(address_map &map)
745 {
746 	map(0x00000, 0x1ffff).bankr("okibank");
747 	map(0x20000, 0x3ffff).rom().region("oki", 0x60000);
748 }
749 
750 
751 //-------------------------------------------------
752 // device_add_mconfig - add device configuration
753 //-------------------------------------------------
754 
device_add_mconfig(machine_config & config)755 void williams_adpcm_sound_device::device_add_mconfig(machine_config &config)
756 {
757 	MC6809E(config, m_cpu, ADPCM_MASTER_CLOCK / 4);
758 	m_cpu->set_addrmap(AS_PROGRAM, &williams_adpcm_sound_device::williams_adpcm_map);
759 
760 	ym2151_device &ym2151(YM2151(config, "ym2151", ADPCM_FM_CLOCK));
761 	ym2151.irq_handler().set_inputline("cpu", M6809_FIRQ_LINE);
762 	ym2151.add_route(ALL_OUTPUTS, *this, 0.10);
763 
764 	AD7524(config, "dac", 0).add_route(ALL_OUTPUTS, *this, 0.10);
765 
766 	okim6295_device &oki(OKIM6295(config, "oki", ADPCM_MASTER_CLOCK/8, okim6295_device::PIN7_HIGH)); // clock frequency & pin 7 not verified
767 	oki.set_addrmap(0, &williams_adpcm_sound_device::williams_adpcm_oki_map);
768 	oki.add_route(ALL_OUTPUTS, *this, 0.15);
769 }
770 
771 
772 //-------------------------------------------------
773 //  device_start - device-specific startup
774 //-------------------------------------------------
775 
device_start()776 void williams_adpcm_sound_device::device_start()
777 {
778 	// configure banks
779 	u8 *rom = memregion("cpu")->base();
780 	m_rombank->configure_entries(0, 8, &rom[0x10000], 0x8000);
781 	membank("romupper")->set_base(&rom[0x10000 + 0x4000 + 7 * 0x8000]);
782 
783 	// expand ADPCM data
784 	rom = memregion("oki")->base();
785 	// it is assumed that U12 is loaded @ 0x00000 and U13 is loaded @ 0x40000
786 	m_okibank->configure_entry(0, &rom[0x40000]);
787 	m_okibank->configure_entry(1, &rom[0x40000]);
788 	m_okibank->configure_entry(2, &rom[0x20000]);
789 	m_okibank->configure_entry(3, &rom[0x00000]);
790 	m_okibank->configure_entry(4, &rom[0xe0000]);
791 	m_okibank->configure_entry(5, &rom[0xc0000]);
792 	m_okibank->configure_entry(6, &rom[0xa0000]);
793 	m_okibank->configure_entry(7, &rom[0x80000]);
794 
795 	// register for save states
796 	save_item(NAME(m_latch));
797 	save_item(NAME(m_talkback));
798 	save_item(NAME(m_sound_int_state));
799 }
800 
801 
802 //-------------------------------------------------
803 //  device_reset - device-specific reset
804 //-------------------------------------------------
805 
device_reset()806 void williams_adpcm_sound_device::device_reset()
807 {
808 	// reset interrupt states
809 	m_sound_int_state = 0;
810 	m_cpu->set_input_line(M6809_FIRQ_LINE, CLEAR_LINE);
811 	m_cpu->set_input_line(M6809_IRQ_LINE, CLEAR_LINE);
812 	m_cpu->set_input_line(INPUT_LINE_NMI, CLEAR_LINE);
813 }
814 
815 
816 //-------------------------------------------------
817 //  device_timer - timer callbacks
818 //-------------------------------------------------
819 
device_timer(emu_timer & timer,device_timer_id id,int param,void * ptr)820 void williams_adpcm_sound_device::device_timer(emu_timer &timer, device_timer_id id, int param, void *ptr)
821 {
822 	switch (id)
823 	{
824 		case TID_COMMAND:
825 			m_latch = param & 0xff;
826 			if (!(param & 0x200))
827 			{
828 				m_cpu->set_input_line(M6809_IRQ_LINE, ASSERT_LINE);
829 				m_sound_int_state = 1;
830 				machine().scheduler().boost_interleave(attotime::zero, attotime::from_usec(100));
831 			}
832 			break;
833 
834 		case TID_IRQ_CLEAR:
835 			m_sound_int_state = 0;
836 			break;
837 	}
838 }
839