1 // license:BSD-3-Clause
2 // copyright-holders:Phil Bennett
3 /***************************************************************************
4 
5     Acclaim RAX Sound Board
6 
7 ****************************************************************************/
8 
9 #include "emu.h"
10 #include "rax.h"
11 #include "speaker.h"
12 
13 
14 /*************************************
15  *
16  *  Constants
17  *
18  *************************************/
19 
20 /* These are some of the control registers. We don't use them all */
21 enum
22 {
23 	IDMA_CONTROL_REG = 0,   /* 3fe0 */
24 	BDMA_INT_ADDR_REG,      /* 3fe1 */
25 	BDMA_EXT_ADDR_REG,      /* 3fe2 */
26 	BDMA_CONTROL_REG,       /* 3fe3 */
27 	BDMA_WORD_COUNT_REG,    /* 3fe4 */
28 	PROG_FLAG_DATA_REG,     /* 3fe5 */
29 	PROG_FLAG_CONTROL_REG,  /* 3fe6 */
30 
31 	S1_AUTOBUF_REG = 15,    /* 3fef */
32 	S1_RFSDIV_REG,          /* 3ff0 */
33 	S1_SCLKDIV_REG,         /* 3ff1 */
34 	S1_CONTROL_REG,         /* 3ff2 */
35 	S0_AUTOBUF_REG,         /* 3ff3 */
36 	S0_RFSDIV_REG,          /* 3ff4 */
37 	S0_SCLKDIV_REG,         /* 3ff5 */
38 	S0_CONTROL_REG,         /* 3ff6 */
39 	S0_MCTXLO_REG,          /* 3ff7 */
40 	S0_MCTXHI_REG,          /* 3ff8 */
41 	S0_MCRXLO_REG,          /* 3ff9 */
42 	S0_MCRXHI_REG,          /* 3ffa */
43 	TIMER_SCALE_REG,        /* 3ffb */
44 	TIMER_COUNT_REG,        /* 3ffc */
45 	TIMER_PERIOD_REG,       /* 3ffd */
46 	WAITSTATES_REG,         /* 3ffe */
47 	SYSCONTROL_REG          /* 3fff */
48 };
49 
50 
51 /*************************************
52  *
53  *  Interface
54  *
55  *************************************/
56 
data_w(uint16_t data)57 void acclaim_rax_device::data_w(uint16_t data)
58 {
59 	m_data_in->write(data);
60 	m_cpu->set_input_line(ADSP2181_IRQL0, ASSERT_LINE);
61 	machine().scheduler().boost_interleave(attotime::zero, attotime::from_usec(5));
62 }
63 
64 
data_r()65 uint16_t acclaim_rax_device::data_r()
66 {
67 	m_adsp_snd_pf0 = 1;
68 	return m_data_out->read();
69 }
70 
71 
72 /*************************************
73  *
74  *  Internal
75  *
76  *************************************/
77 
adsp_control_r(offs_t offset)78 uint16_t acclaim_rax_device::adsp_control_r(offs_t offset)
79 {
80 	uint16_t res = 0;
81 
82 	switch (offset)
83 	{
84 		case PROG_FLAG_DATA_REG:
85 			res = m_adsp_snd_pf0;
86 			break;
87 		default:
88 			res = m_control_regs[offset];
89 	}
90 
91 	return res;
92 }
93 
adsp_control_w(offs_t offset,uint16_t data)94 void acclaim_rax_device::adsp_control_w(offs_t offset, uint16_t data)
95 {
96 	m_control_regs[offset] = data;
97 
98 	switch (offset)
99 	{
100 		case 0x1:
101 			m_control_regs[BDMA_INT_ADDR_REG] = data & 0x3fff;
102 			break;
103 		case 0x2:
104 			m_control_regs[BDMA_EXT_ADDR_REG] = data & 0x3fff;
105 			break;
106 		case 0x3:
107 			m_control_regs[BDMA_CONTROL_REG] = data & 0xff0f;
108 			break;
109 
110 		case 0x4:
111 		{
112 			m_control_regs[BDMA_WORD_COUNT_REG] = data & 0x3fff;
113 
114 			const uint8_t *adsp_rom = &m_rom[m_rom_bank * 0x400000];
115 
116 			uint32_t page = (m_control_regs[BDMA_CONTROL_REG] >> 8) & 0xff;
117 			uint32_t dir = (m_control_regs[BDMA_CONTROL_REG] >> 2) & 1;
118 			uint32_t type = m_control_regs[BDMA_CONTROL_REG] & 3;
119 			uint32_t src_addr = (page << 14) | m_control_regs[BDMA_EXT_ADDR_REG];
120 
121 			uint32_t count = m_control_regs[BDMA_WORD_COUNT_REG];
122 
123 			address_space* addr_space = (type == 0 ? m_program : m_data);
124 
125 			if (dir == 0)
126 			{
127 				if (type == 0)
128 				{
129 					while (count)
130 					{
131 						uint32_t src_dword = (adsp_rom[src_addr + 0] << 16) | (adsp_rom[src_addr + 1] << 8) | adsp_rom[src_addr + 2];
132 
133 						addr_space->write_dword(m_control_regs[BDMA_INT_ADDR_REG], src_dword);
134 
135 						src_addr += 3;
136 						++m_control_regs[BDMA_INT_ADDR_REG];
137 						--count;
138 					}
139 				}
140 				else if (type == 1)
141 				{
142 					while (count)
143 					{
144 						uint16_t src_word = (adsp_rom[src_addr + 0] << 8) | adsp_rom[src_addr + 1];
145 
146 						addr_space->write_word(m_control_regs[BDMA_INT_ADDR_REG], src_word);
147 
148 						src_addr += 2;
149 						++m_control_regs[BDMA_INT_ADDR_REG];
150 						--count;
151 					}
152 				}
153 				else
154 				{
155 					int shift = type == 2 ? 8 : 0;
156 
157 					while (count)
158 					{
159 						uint16_t src_word = adsp_rom[src_addr] << shift;
160 
161 						addr_space->write_word(m_control_regs[BDMA_INT_ADDR_REG], src_word);
162 
163 						++src_addr;
164 						++m_control_regs[BDMA_INT_ADDR_REG];
165 						--count;
166 					}
167 				}
168 			}
169 			else
170 			{
171 				// TODO: last stage in Batman Forever!?
172 				// page = 0, dir = 1, type = 1, src_addr = 0xfd
173 				fatalerror("%s DMA to byte memory!",this->tag());
174 			}
175 
176 			attotime word_period = attotime::from_hz(m_cpu->unscaled_clock());
177 			attotime period = word_period * (data & 0x3fff) * 1;
178 			m_dma_timer->adjust(period, src_addr, period);
179 
180 			break;
181 		}
182 
183 		case S1_AUTOBUF_REG:
184 			/* autobuffer off: nuke the timer, and disable the DAC */
185 			if ((data & 0x0002) == 0)
186 			{
187 				m_dmadac[1]->enable(0);
188 			}
189 			break;
190 
191 		case S0_AUTOBUF_REG:
192 			/* autobuffer off: nuke the timer, and disable the DAC */
193 			if ((data & 0x0002) == 0)
194 			{
195 				m_dmadac[0]->enable(0);
196 				m_reg_timer->reset();
197 			}
198 			break;
199 
200 		case S1_CONTROL_REG:
201 			if (((data >> 4) & 3) == 2)
202 				fatalerror("DCS: Oh no!, the data is compressed with u-law encoding\n");
203 			if (((data >> 4) & 3) == 3)
204 				fatalerror("DCS: Oh no!, the data is compressed with A-law encoding\n");
205 			break;
206 
207 		case PROG_FLAG_DATA_REG:
208 			logerror("PFLAGS: %x\n", data);
209 			break;
210 		case PROG_FLAG_CONTROL_REG:
211 			logerror("PFLAG CTRL: %x\n", data);
212 			break;
213 		default:
214 			logerror("Unhandled register: %x %x\n", 0x3fe0 + offset, data);
215 	}
216 }
217 
218 
TIMER_DEVICE_CALLBACK_MEMBER(acclaim_rax_device::dma_timer_callback)219 TIMER_DEVICE_CALLBACK_MEMBER( acclaim_rax_device::dma_timer_callback )
220 {
221 	/* Update external address count and page */
222 	m_control_regs[BDMA_WORD_COUNT_REG] = 0;
223 	m_control_regs[BDMA_EXT_ADDR_REG] = param & 0x3fff;
224 	m_control_regs[BDMA_CONTROL_REG] &= ~0xff00;
225 	m_control_regs[BDMA_CONTROL_REG] |= ((param >> 14) & 0xff) << 8;
226 
227 	if (m_control_regs[BDMA_CONTROL_REG] & 8)
228 		m_cpu->pulse_input_line(INPUT_LINE_RESET, attotime::zero);
229 	else
230 		m_cpu->pulse_input_line(ADSP2181_BDMA, m_cpu->minimum_quantum_time());
231 
232 	timer.adjust(attotime::never);
233 }
234 
235 
update_data_ram_bank()236 void acclaim_rax_device::update_data_ram_bank()
237 {
238 	if (m_dmovlay_val == 0)
239 		membank("databank")->set_entry(0);
240 	else
241 		membank("databank")->set_entry(1 + m_data_bank);
242 }
243 
ram_bank_w(uint16_t data)244 void acclaim_rax_device::ram_bank_w(uint16_t data)
245 {
246 	// Note: The PCB has two unstuffed RAM locations
247 	m_data_bank = data & 3;
248 	update_data_ram_bank();
249 }
250 
rom_bank_w(uint16_t data)251 void acclaim_rax_device::rom_bank_w(uint16_t data)
252 {
253 	m_rom_bank = data;
254 }
255 
host_r()256 uint16_t acclaim_rax_device::host_r()
257 {
258 	m_cpu->set_input_line(ADSP2181_IRQL0, CLEAR_LINE);
259 	return m_data_in->read();
260 }
261 
host_w(uint16_t data)262 void acclaim_rax_device::host_w(uint16_t data)
263 {
264 	m_data_out->write(data);
265 	m_adsp_snd_pf0 = 0;
266 }
267 
268 
269 /*************************************
270  *
271  *  CPU memory map & config
272  *
273  *************************************/
274 
adsp_program_map(address_map & map)275 void acclaim_rax_device::adsp_program_map(address_map &map)
276 {
277 	map.unmap_value_high();
278 	map(0x0000, 0x3fff).ram().share("adsp_pram");
279 }
280 
adsp_data_map(address_map & map)281 void acclaim_rax_device::adsp_data_map(address_map &map)
282 {
283 	map.unmap_value_high();
284 	map(0x0000, 0x1fff).bankrw("databank");
285 	map(0x2000, 0x3fdf).ram(); // Internal RAM
286 	map(0x3fe0, 0x3fff).rw(FUNC(acclaim_rax_device::adsp_control_r), FUNC(acclaim_rax_device::adsp_control_w));
287 }
288 
adsp_io_map(address_map & map)289 void acclaim_rax_device::adsp_io_map(address_map &map)
290 {
291 	map.unmap_value_high();
292 	map(0x0000, 0x0000).w(FUNC(acclaim_rax_device::ram_bank_w));
293 	map(0x0001, 0x0001).w(FUNC(acclaim_rax_device::rom_bank_w));
294 	map(0x0003, 0x0003).rw(FUNC(acclaim_rax_device::host_r), FUNC(acclaim_rax_device::host_w));
295 }
296 
297 
device_start()298 void acclaim_rax_device::device_start()
299 {
300 	m_program = &m_cpu->space(AS_PROGRAM);
301 	m_data = &m_cpu->space(AS_DATA);
302 
303 	// 1 bank for internal
304 	m_banked_ram = make_unique_clear<uint16_t[]>(0x2000 * 5);
305 	membank("databank")->configure_entries(0, 5, &m_banked_ram[0], 0x2000*sizeof(uint16_t));
306 }
307 
device_reset()308 void acclaim_rax_device::device_reset()
309 {
310 	/* Load 32 program words (96 bytes) via BDMA */
311 	for (int i = 0; i < 32; i ++)
312 	{
313 		uint32_t word;
314 
315 		word = m_rom[i*3 + 0] << 16;
316 		word |= m_rom[i*3 + 1] << 8;
317 		word |= m_rom[i*3 + 2];
318 
319 		m_adsp_pram[i] = word;
320 	}
321 
322 	m_adsp_snd_pf0 = 1;
323 	m_rom_bank = 0;
324 
325 	/* initialize our state structure and install the transmit callback */
326 	m_size[0] = 0;
327 	m_incs[0] = 0;
328 	m_ireg[0] = 0;
329 
330 	/* initialize the ADSP control regs */
331 	memset(m_control_regs, 0, sizeof(m_control_regs));
332 
333 	m_dmovlay_val = 0;
334 	m_data_bank = 0;
335 	update_data_ram_bank();
336 }
337 
338 
adsp_irq(int which)339 void acclaim_rax_device::adsp_irq(int which)
340 {
341 	if (which != 0)
342 		return;
343 
344 	/* get the index register */
345 	int reg = m_cpu->state_int(ADSP2100_I0 + m_ireg[which]);
346 
347 	/* copy the current data into the buffer */
348 	int count = m_size[which] / (4 * (m_incs[which] ? m_incs[which] : 1));
349 
350 	int16_t buffer[0x100];
351 
352 	for (uint32_t i = 0; i < count; i++)
353 	{
354 		buffer[i] = m_data->read_word(reg);
355 		reg += m_incs[which];
356 	}
357 
358 	for (int i = 0; i < 2; i++)
359 	{
360 		m_dmadac[i]->flush();
361 		m_dmadac[i]->transfer(i, 1, 2, count/2, buffer);
362 	}
363 
364 	/* check for wrapping */
365 	if (reg >= m_ireg_base[which] + m_size[which])
366 	{
367 		/* reset the base pointer */
368 		reg = m_ireg_base[which];
369 	}
370 
371 	m_cpu->set_state_int(ADSP2100_I0 + m_ireg[which], reg);
372 }
373 
TIMER_DEVICE_CALLBACK_MEMBER(acclaim_rax_device::adsp_irq0)374 TIMER_DEVICE_CALLBACK_MEMBER( acclaim_rax_device::adsp_irq0 )
375 {
376 	adsp_irq(0);
377 }
378 
379 
380 
recompute_sample_rate(int which)381 void acclaim_rax_device::recompute_sample_rate(int which)
382 {
383 	/* calculate how long until we generate an interrupt */
384 
385 	/* frequency the time per each bit sent */
386 	attotime sample_period = attotime::from_hz(m_cpu->unscaled_clock()) * (1 * (m_control_regs[which ? S1_SCLKDIV_REG : S0_SCLKDIV_REG] + 1));
387 
388 	/* now put it down to samples, so we know what the channel frequency has to be */
389 	sample_period = sample_period * (16 * 1);
390 	for (auto &dmadac : m_dmadac)
391 	{
392 		dmadac->set_frequency(sample_period.as_hz());
393 		dmadac->enable(1);
394 	}
395 
396 	/* fire off a timer which will hit every half-buffer */
397 	if (m_incs[which])
398 	{
399 		attotime period = (sample_period * m_size[which]) / (4 * 2 * m_incs[which]);
400 		m_reg_timer->adjust(period, 0, period);
401 	}
402 }
403 
adsp_sound_tx_callback(offs_t offset,uint32_t data)404 void acclaim_rax_device::adsp_sound_tx_callback(offs_t offset, uint32_t data)
405 {
406 	int which = offset;
407 
408 	if (which != 0)
409 		return;
410 
411 	int autobuf_reg = which ? S1_AUTOBUF_REG : S0_AUTOBUF_REG;
412 
413 	/* check if SPORT1 is enabled */
414 	if (m_control_regs[SYSCONTROL_REG] & (which ? 0x0800 : 0x1000)) /* bit 11 */
415 	{
416 		/* we only support autobuffer here (which is what this thing uses), bail if not enabled */
417 		if (m_control_regs[autobuf_reg] & 0x0002) /* bit 1 */
418 		{
419 			/* get the autobuffer registers */
420 			int     mreg, lreg;
421 			uint16_t  source;
422 
423 			m_ireg[which] = (m_control_regs[autobuf_reg] >> 9) & 7;
424 			mreg = (m_control_regs[autobuf_reg] >> 7) & 3;
425 			mreg |= m_ireg[which] & 0x04; /* msb comes from ireg */
426 			lreg = m_ireg[which];
427 
428 			/* now get the register contents in a more legible format */
429 			/* we depend on register indexes to be continuous (which is the case in our core) */
430 			source = m_cpu->state_int(ADSP2100_I0 + m_ireg[which]);
431 			m_incs[which] = m_cpu->state_int(ADSP2100_M0 + mreg);
432 			m_size[which] = m_cpu->state_int(ADSP2100_L0 + lreg);
433 
434 			/* get the base value, since we need to keep it around for wrapping */
435 			source -= m_incs[which];
436 
437 			/* make it go back one so we dont lose the first sample */
438 			m_cpu->set_state_int(ADSP2100_I0 + m_ireg[which], source);
439 
440 			/* save it as it is now */
441 			m_ireg_base[which] = source;
442 
443 			/* recompute the sample rate and timer */
444 			recompute_sample_rate(which);
445 			return;
446 		}
447 		else
448 			logerror( "ADSP SPORT1: trying to transmit and autobuffer not enabled!\n" );
449 	}
450 
451 	/* if we get there, something went wrong. Disable playing */
452 	for (auto &dmadac : m_dmadac)
453 		dmadac->enable(0);
454 
455 	/* remove timer */
456 	m_reg_timer->reset();
457 }
458 
dmovlay_callback(uint32_t data)459 void acclaim_rax_device::dmovlay_callback(uint32_t data)
460 {
461 	if (data < 0 || data > 1)
462 	{
463 		fatalerror("dmovlay_callback: Error! dmovlay called with value = %X\n", data);
464 	}
465 	else
466 	{
467 		m_dmovlay_val = data;
468 		update_data_ram_bank();
469 	}
470 }
471 
472 
473 DEFINE_DEVICE_TYPE(ACCLAIM_RAX, acclaim_rax_device, "rax_audio", "Acclaim RAX")
474 
475 //-------------------------------------------------
476 //  acclaim_rax_device - constructor
477 //-------------------------------------------------
478 
acclaim_rax_device(const machine_config & mconfig,const char * tag,device_t * owner,uint32_t clock)479 acclaim_rax_device::acclaim_rax_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
480 	: device_t(mconfig, ACCLAIM_RAX, tag, owner, clock)
481 	, m_cpu(*this, "adsp")
482 	, m_dmadac(*this, { "dacl", "dacr" })
483 	, m_reg_timer(*this, "adsp_reg_timer")
484 	, m_dma_timer(*this, "adsp_dma_timer")
485 	, m_adsp_pram(*this, "adsp_pram")
486 	, m_adsp_data_bank(*this, "databank")
487 	, m_rom(*this, DEVICE_SELF)
488 	, m_data_in(*this, "data_in")
489 	, m_data_out(*this, "data_out")
490 {
491 
492 }
493 
494 //-------------------------------------------------
495 // device_add_mconfig - add device configuration
496 //-------------------------------------------------
497 
device_add_mconfig(machine_config & config)498 void acclaim_rax_device::device_add_mconfig(machine_config &config)
499 {
500 	ADSP2181(config, m_cpu, XTAL(16'670'000));
501 	m_cpu->sport_tx().set(FUNC(acclaim_rax_device::adsp_sound_tx_callback)); /* callback for serial transmit */
502 	m_cpu->dmovlay().set(FUNC(acclaim_rax_device::dmovlay_callback)); /* callback for adsp 2181 dmovlay instruction */
503 	m_cpu->set_addrmap(AS_PROGRAM, &acclaim_rax_device::adsp_program_map);
504 	m_cpu->set_addrmap(AS_DATA, &acclaim_rax_device::adsp_data_map);
505 	m_cpu->set_addrmap(AS_IO, &acclaim_rax_device::adsp_io_map);
506 
507 	TIMER(config, "adsp_reg_timer").configure_generic(FUNC(acclaim_rax_device::adsp_irq0));
508 	TIMER(config, "adsp_dma_timer").configure_generic(FUNC(acclaim_rax_device::dma_timer_callback));
509 
510 	GENERIC_LATCH_16(config, m_data_in);
511 	GENERIC_LATCH_16(config, m_data_out);
512 
513 	SPEAKER(config, "lspeaker").front_left();
514 	SPEAKER(config, "rspeaker").front_right();
515 
516 	DMADAC(config, "dacl").add_route(ALL_OUTPUTS, "lspeaker", 1.0);
517 	DMADAC(config, "dacr").add_route(ALL_OUTPUTS, "rspeaker", 1.0);
518 }
519 
520