summaryrefslogtreecommitdiffstatshomepage
path: root/src/mame/audio/namco54.c
blob: 5a4dacf4dc2c886e7e3c924c89dc23262eae93ba (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
/***************************************************************************

Namco 54XX

This custom chip is a Fujitsu MB8844 MCU programmed to act as a noise
generator. It is used for explosions, the shoot sound in Bosconian, and the
tire screech sound in Pole Position.

CMD = command from main CPU
OUTn = sound outputs (3 channels)

The chip reads the command when the /IRQ is pulled down.

      +------+
 EXTAL|1   28|Vcc
  XTAL|2   27|CMD7
/RESET|3   26|CMD6
OUT0.0|4   25|CMD5
OUT0.1|5   24|CMD4
OUT0.2|6   23|/IRQ
OUT0.3|7   22|n.c. [1]
OUT1.0|8   21|n.c. [1]
OUT1.1|9   20|OUT2.3
OUT1.2|10  19|OUT2.2
OUT1.3|11  18|OUT2.1
  CMD0|12  17|OUT2.0
  CMD1|13  16|CMD3
   GND|14  15|CMD2
      +------+


[1] The RNG that drives the type A output is output on pin 21, and the one that
drives the type B output is output on pin 22, but those pins are not connected
on the board.


The command format is very simple:

0x: nop
1x: play sound type A
2x: play sound type B
3x: set parameters (type A) (followed by 4 bytes)
4x: set parameters (type B) (followed by 4 bytes)
5x: play sound type C
6x: set parameters (type C) (followed by 5 bytes)
7x: set volume for sound type C to x
8x-Fx: nop

***************************************************************************/

#include "driver.h"
#include "namco54.h"
#include "cpu/mb88xx/mb88xx.h"


static UINT8 latched_cmd;

static TIMER_CALLBACK( namco_54xx_latch_callback )
{
	latched_cmd = param;
}

static READ8_HANDLER( namco_54xx_K_r )
{
	return latched_cmd >> 4;
}

static READ8_HANDLER( namco_54xx_R0_r )
{
	return latched_cmd & 0x0f;
}


static WRITE8_HANDLER( namco_54xx_O_w )
{
	UINT8 out = (data & 0x0f);
	if (data & 0x10)
		discrete_sound_w(NAMCO_54XX_1_DATA, out);
	else
		discrete_sound_w(NAMCO_54XX_0_DATA, out);
}

static WRITE8_HANDLER( namco_54xx_R1_w )
{
	UINT8 out = (data & 0x0f);

	discrete_sound_w(NAMCO_54XX_2_DATA, out);
}



ADDRESS_MAP_START( namco_54xx_map_program, ADDRESS_SPACE_PROGRAM, 8 )
	AM_RANGE(0x000, 0x3ff) AM_ROM
ADDRESS_MAP_END

ADDRESS_MAP_START( namco_54xx_map_data, ADDRESS_SPACE_DATA, 8 )
	AM_RANGE(0x00, 0x3f) AM_RAM
ADDRESS_MAP_END

ADDRESS_MAP_START( namco_54xx_map_io, ADDRESS_SPACE_IO, 8 )
	AM_RANGE(MB88_PORTK,  MB88_PORTK)  AM_READ(namco_54xx_K_r)
	AM_RANGE(MB88_PORTO,  MB88_PORTO)  AM_WRITE(namco_54xx_O_w)
	AM_RANGE(MB88_PORTR0, MB88_PORTR0) AM_READ(namco_54xx_R0_r)
	AM_RANGE(MB88_PORTR1, MB88_PORTR1) AM_WRITE(namco_54xx_R1_w)
	AM_RANGE(MB88_PORTR2, MB88_PORTR2) AM_NOP
ADDRESS_MAP_END



static TIMER_CALLBACK( namco_54xx_irq_clear )
{
	cpunum_set_input_line(param, 0, CLEAR_LINE);
}

void namco_54xx_write(UINT8 data)
{
	int cpunum = mame_find_cpu_index(Machine, CPUTAG_54XX);

	if (cpunum == -1)
		return;

	timer_call_after_resynch(data, namco_54xx_latch_callback);

	cpunum_set_input_line(cpunum, 0, ASSERT_LINE);

	// The execution time of one instruction is ~4us, so we must make sure to
	// give the cpu time to poll the /IRQ input before we clear it.
	// The input clock to the 06XX interface chip is 64H, that is
	// 18432000/6/64 = 48kHz, so it makes sense for the irq line to be
	// asserted for one clock cycle ~= 21us.
	timer_set(ATTOTIME_IN_USEC(21), cpunum, namco_54xx_irq_clear);
}