1
/***************************************************************************
5
This custom chip is a Fujitsu MB8844 MCU programmed to act as a noise
6
generator. It is used for explosions, the shoot sound in Bosconian,
7
and the tire screech sound in Pole Position.
9
CMD = command from main CPU
10
OUTn = sound outputs (3 channels)
12
The chip reads the command when the /IRQ is pulled down.
18
(OUT0.0) O0|4 25|K1 (CMD5)
19
(OUT0.1) O1|5 24|K0 (CMD4)
20
(OUT0.2) O2|6 23|R10/IRQ
21
(OUT0.3) O3|7 22|R9/TC
23
(OUT1.1) O5|9 20|R7 (OUT2.3)
24
(OUT1.2) O6|10 19|R6 (OUT2.2)
25
(OUT1.3) O7|11 18|R5 (OUT2.1)
26
(CMD0) R0|12 17|R4 (OUT2.0)
27
(CMD1) R1|13 16|R3 (CMD3)
31
[1] The RNG that drives the type A output is output on pin 21, and
32
the one that drives the type B output is output on pin 22, but those
33
pins are not connected on the board.
36
The command format is very simple:
41
3x: set parameters (type A) (followed by 4 bytes)
42
4x: set parameters (type B) (followed by 4 bytes)
44
6x: set parameters (type C) (followed by 5 bytes)
45
7x: set volume for sound type C to x
48
***************************************************************************/
52
#include "cpu/mb88xx/mb88xx.h"
54
typedef struct _namco_54xx_state namco_54xx_state;
55
struct _namco_54xx_state
63
INLINE namco_54xx_state *get_safe_token(device_t *device)
65
assert(device != NULL);
66
assert(device->type() == NAMCO_54XX);
68
return (namco_54xx_state *)downcast<legacy_device_base *>(device)->token();
73
static TIMER_CALLBACK( namco_54xx_latch_callback )
75
namco_54xx_state *state = get_safe_token((device_t *)ptr);
76
state->m_latched_cmd = param;
79
static READ8_HANDLER( namco_54xx_K_r )
81
namco_54xx_state *state = get_safe_token(space->device().owner());
82
return state->m_latched_cmd >> 4;
85
static READ8_HANDLER( namco_54xx_R0_r )
87
namco_54xx_state *state = get_safe_token(space->device().owner());
88
return state->m_latched_cmd & 0x0f;
92
static WRITE8_HANDLER( namco_54xx_O_w )
94
namco_54xx_state *state = get_safe_token(space->device().owner());
95
UINT8 out = (data & 0x0f);
97
discrete_sound_w(state->m_discrete, NAMCO_54XX_1_DATA(state->m_basenode), out);
99
discrete_sound_w(state->m_discrete, NAMCO_54XX_0_DATA(state->m_basenode), out);
102
static WRITE8_HANDLER( namco_54xx_R1_w )
104
namco_54xx_state *state = get_safe_token(space->device().owner());
105
UINT8 out = (data & 0x0f);
107
discrete_sound_w(state->m_discrete, NAMCO_54XX_2_DATA(state->m_basenode), out);
113
static TIMER_CALLBACK( namco_54xx_irq_clear )
115
namco_54xx_state *state = get_safe_token((device_t *)ptr);
116
device_set_input_line(state->m_cpu, 0, CLEAR_LINE);
119
WRITE8_DEVICE_HANDLER( namco_54xx_write )
121
namco_54xx_state *state = get_safe_token(device);
123
device->machine().scheduler().synchronize(FUNC(namco_54xx_latch_callback), data, (void *)device);
125
device_set_input_line(state->m_cpu, 0, ASSERT_LINE);
127
// The execution time of one instruction is ~4us, so we must make sure to
128
// give the cpu time to poll the /IRQ input before we clear it.
129
// The input clock to the 06XX interface chip is 64H, that is
130
// 18432000/6/64 = 48kHz, so it makes sense for the irq line to be
131
// asserted for one clock cycle ~= 21us.
132
device->machine().scheduler().timer_set(attotime::from_usec(21), FUNC(namco_54xx_irq_clear), 0, (void *)device);
136
/***************************************************************************
138
***************************************************************************/
140
static ADDRESS_MAP_START( namco_54xx_map_io, AS_IO, 8 )
141
AM_RANGE(MB88_PORTK, MB88_PORTK) AM_READ(namco_54xx_K_r)
142
AM_RANGE(MB88_PORTO, MB88_PORTO) AM_WRITE(namco_54xx_O_w)
143
AM_RANGE(MB88_PORTR0, MB88_PORTR0) AM_READ(namco_54xx_R0_r)
144
AM_RANGE(MB88_PORTR1, MB88_PORTR1) AM_WRITE(namco_54xx_R1_w)
145
AM_RANGE(MB88_PORTR2, MB88_PORTR2) AM_NOP
149
static MACHINE_CONFIG_FRAGMENT( namco_54xx )
150
MCFG_CPU_ADD("mcu", MB8844, DERIVED_CLOCK(1,1)) /* parent clock, internally divided by 6 */
151
MCFG_CPU_IO_MAP(namco_54xx_map_io)
155
ROM_START( namco_54xx )
156
ROM_REGION( 0x400, "mcu", ROMREGION_LOADBYNAME )
157
ROM_LOAD( "54xx.bin", 0x0000, 0x0400, CRC(ee7357e0) SHA1(01bdf984a49e8d0cc8761b2cc162fd6434d5afbe) )
161
/*-------------------------------------------------
162
device start callback
163
-------------------------------------------------*/
165
static DEVICE_START( namco_54xx )
167
namco_54xx_config *config = (namco_54xx_config *)downcast<const legacy_device_base *>(device)->inline_config();
168
namco_54xx_state *state = get_safe_token(device);
172
state->m_cpu = device->subdevice("mcu");
173
assert(state->m_cpu != NULL);
175
/* find the attached discrete sound device */
176
assert(config->discrete != NULL);
177
state->m_discrete = device->machine().device(config->discrete);
178
assert(state->m_discrete != NULL);
179
state->m_basenode = config->firstnode;
183
/*-------------------------------------------------
185
-------------------------------------------------*/
187
static const char DEVTEMPLATE_SOURCE[] = __FILE__;
189
#define DEVTEMPLATE_ID(p,s) p##namco_54xx##s
190
#define DEVTEMPLATE_FEATURES DT_HAS_START | DT_HAS_ROM_REGION | DT_HAS_MACHINE_CONFIG | DT_HAS_INLINE_CONFIG
191
#define DEVTEMPLATE_NAME "Namco 54xx"
192
#define DEVTEMPLATE_SHORTNAME "namco54"
193
#define DEVTEMPLATE_FAMILY "Namco I/O"
194
#include "devtempl.h"
197
DEFINE_LEGACY_DEVICE(NAMCO_54XX, namco_54xx);