1 // license:BSD-3-Clause
2 // copyright-holders:Aaron Giles
3 /***************************************************************************
4 
5     Namco 54XX
6 
7     This custom chip is a Fujitsu MB8844 MCU programmed to act as a noise
8     generator. It is used for explosions, the shoot sound in Bosconian,
9     and the tire screech sound in Pole Position.
10 
11     CMD = command from main CPU
12     OUTn = sound outputs (3 channels)
13 
14     The chip reads the command when the /IRQ is pulled down.
15 
16                        +------+
17                      EX|1   28|Vcc
18                       X|2   27|K3 (CMD7)
19                  /RESET|3   26|K2 (CMD6)
20             (OUT0.0) O0|4   25|K1 (CMD5)
21             (OUT0.1) O1|5   24|K0 (CMD4)
22             (OUT0.2) O2|6   23|R10/IRQ
23             (OUT0.3) O3|7   22|R9/TC
24             (OUT1.0) O4|8   21|R8
25             (OUT1.1) O5|9   20|R7 (OUT2.3)
26             (OUT1.2) O6|10  19|R6 (OUT2.2)
27             (OUT1.3) O7|11  18|R5 (OUT2.1)
28               (CMD0) R0|12  17|R4 (OUT2.0)
29               (CMD1) R1|13  16|R3 (CMD3)
30                     GND|14  15|R2 (CMD2)
31                        +------+
32 
33     [1] The RNG that drives the type A output is output on pin 21, and
34     the one that drives the type B output is output on pin 22, but those
35     pins are not connected on the board.
36 
37 
38     The command format is very simple:
39 
40     0x: nop
41     1x: play sound type A
42     2x: play sound type B
43     3x: set parameters (type A) (followed by 4 bytes)
44     4x: set parameters (type B) (followed by 4 bytes)
45     5x: play sound type C
46     6x: set parameters (type C) (followed by 5 bytes)
47     7x: set volume for sound type C to x
48     8x-Fx: nop
49 
50 ***************************************************************************/
51 
52 #include "emu.h"
53 #include "namco54.h"
54 
TIMER_CALLBACK_MEMBER(namco_54xx_device::latch_callback)55 TIMER_CALLBACK_MEMBER( namco_54xx_device::latch_callback )
56 {
57 	m_latched_cmd = param;
58 }
59 
WRITE_LINE_MEMBER(namco_54xx_device::reset)60 WRITE_LINE_MEMBER( namco_54xx_device::reset )
61 {
62 	// The incoming signal is active low
63 	m_cpu->set_input_line(INPUT_LINE_RESET, !state);
64 }
65 
K_r()66 uint8_t namco_54xx_device::K_r()
67 {
68 	return m_latched_cmd >> 4;
69 }
70 
R0_r()71 uint8_t namco_54xx_device::R0_r()
72 {
73 	return m_latched_cmd & 0x0f;
74 }
75 
O_w(uint8_t data)76 void namco_54xx_device::O_w(uint8_t data)
77 {
78 	uint8_t out = (data & 0x0f);
79 	if (data & 0x10)
80 		m_discrete->write(NAMCO_54XX_1_DATA(m_basenode), out);
81 	else
82 		m_discrete->write(NAMCO_54XX_0_DATA(m_basenode), out);
83 }
84 
R1_w(uint8_t data)85 void namco_54xx_device::R1_w(uint8_t data)
86 {
87 	uint8_t out = (data & 0x0f);
88 
89 	m_discrete->write(NAMCO_54XX_2_DATA(m_basenode), out);
90 }
91 
92 
write(uint8_t data)93 void namco_54xx_device::write(uint8_t data)
94 {
95 	machine().scheduler().synchronize(timer_expired_delegate(FUNC(namco_54xx_device::latch_callback),this), data);
96 
97 	// TODO: should use chip_select line for this
98 	m_cpu->pulse_input_line(0, m_irq_duration);
99 }
100 
WRITE_LINE_MEMBER(namco_54xx_device::chip_select)101 WRITE_LINE_MEMBER( namco_54xx_device::chip_select )
102 {
103 	// TODO: broken sound when using this
104 	//m_cpu->set_input_line(0, state);
105 }
106 
107 
108 /***************************************************************************
109     DEVICE INTERFACE
110 ***************************************************************************/
111 
112 ROM_START( namco_54xx )
113 	ROM_REGION( 0x400, "mcu", 0 )
CRC(ee7357e0)114 	ROM_LOAD( "54xx.bin",     0x0000, 0x0400, CRC(ee7357e0) SHA1(01bdf984a49e8d0cc8761b2cc162fd6434d5afbe) )
115 ROM_END
116 
117 DEFINE_DEVICE_TYPE(NAMCO_54XX, namco_54xx_device, "namco54", "Namco 54xx")
118 
119 namco_54xx_device::namco_54xx_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
120 	: device_t(mconfig, NAMCO_54XX, tag, owner, clock),
121 	m_cpu(*this, "mcu"),
122 	m_discrete(*this, finder_base::DUMMY_TAG),
123 	m_irq_duration(attotime::from_usec(100)),
124 	m_basenode(0),
125 	m_latched_cmd(0)
126 {
127 }
128 
129 //-------------------------------------------------
130 //  device_start - device-specific startup
131 //-------------------------------------------------
132 
device_start()133 void namco_54xx_device::device_start()
134 {
135 	save_item(NAME(m_latched_cmd));
136 }
137 
138 //-------------------------------------------------
139 // device_add_mconfig - add device configuration
140 //-------------------------------------------------
141 
device_add_mconfig(machine_config & config)142 void namco_54xx_device::device_add_mconfig(machine_config &config)
143 {
144 	MB8844(config, m_cpu, DERIVED_CLOCK(1,1)); /* parent clock, internally divided by 6 */
145 	m_cpu->read_k().set(FUNC(namco_54xx_device::K_r));
146 	m_cpu->write_o().set(FUNC(namco_54xx_device::O_w));
147 	m_cpu->read_r<0>().set(FUNC(namco_54xx_device::R0_r));
148 	m_cpu->write_r<1>().set(FUNC(namco_54xx_device::R1_w));
149 }
150 
151 //-------------------------------------------------
152 //  device_rom_region - return a pointer to the
153 //  the device's ROM definitions
154 //-------------------------------------------------
155 
device_rom_region() const156 const tiny_rom_entry *namco_54xx_device::device_rom_region() const
157 {
158 	return ROM_NAME(namco_54xx );
159 }
160