1 // license:BSD-3-Clause
2 // copyright-holders:Aaron Giles
3 /***************************************************************************
4 
5     Namco 52XX
6 
7     This instance of the Fujitsu MB8843 MCU is programmed to act as a
8     sample player. It is used by just a few games, most notably Bosconian
9     and Pole Position.
10 
11     A0-A15 = address to read from sample ROMs
12     D0-D7 = data from sample ROMs
13     CMD0-CMD3 = command from CPU (sample to play, 0 = none)
14     OUT0-OUT3 = sound output
15 
16                   +------+
17                 EX|1   42|Vcc
18                  X|2   41|K3 (CMD3)
19             /RESET|3   40|K2 (CMD2)
20               /IRQ|4   39|K1 (CMD1)
21          (n.c.) SO|5   38|K0 (CMD0)
22             [1] SI|6   37|R15 (A7)
23      (n.c.) /SC/TO|7   36|R14 (A6)
24            [2] /TC|8   35|R13 (A5)
25          (OUT0) P0|9   34|R12 (A4)
26          (OUT1) P1|10  33|R11 (A3)
27          (OUT2) P2|11  32|R10 (A2)
28          (OUT3) P3|12  31|R9 (A1)
29            (A8) O0|13  30|R8 (A0)
30            (A9) O1|14  29|R7 (D7)
31           (A10) O2|15  28|R6 (D6)
32           (A11) O3|16  27|R5 (D5)
33           (A12) O4|17  26|R4 (D4)
34           (A13) O5|18  25|R3 (D3)
35           (A14) O6|19  24|R2 (D2)
36           (A15) O7|20  23|R1 (D1)
37                GND|21  22|R0 (D0)
38                   +------+
39 
40     [1] in polepos, +5V; in bosco, GND
41         this value controls the ROM addressing mode:
42            if 0 (GND), A12-A15 are direct active-low chip enables
43            if 1 (Vcc), A12-A15 are address lines
44 
45     [2] in polepos, GND; in bosco, output from a 555 timer
46         this value is an external timer, which is used for some samples
47 
48 ***************************************************************************/
49 
50 #include "emu.h"
51 #include "namco52.h"
52 
WRITE_LINE_MEMBER(namco_52xx_device::reset)53 WRITE_LINE_MEMBER( namco_52xx_device::reset )
54 {
55 	// The incoming signal is active low
56 	m_cpu->set_input_line(INPUT_LINE_RESET, !state);
57 }
58 
TIMER_CALLBACK_MEMBER(namco_52xx_device::latch_callback)59 TIMER_CALLBACK_MEMBER( namco_52xx_device::latch_callback )
60 {
61 	m_latched_cmd = param;
62 }
63 
K_r()64 uint8_t namco_52xx_device::K_r()
65 {
66 	return m_latched_cmd & 0x0f;
67 }
68 
READ_LINE_MEMBER(namco_52xx_device::SI_r)69 READ_LINE_MEMBER( namco_52xx_device::SI_r )
70 {
71 	return m_si(0) ? 1 : 0;
72 }
73 
R0_r()74 uint8_t namco_52xx_device::R0_r()
75 {
76 	return m_romread(m_address) & 0x0f;
77 }
78 
R1_r()79 uint8_t namco_52xx_device::R1_r()
80 {
81 	return m_romread(m_address) >> 4;
82 }
83 
84 
P_w(uint8_t data)85 void namco_52xx_device::P_w(uint8_t data)
86 {
87 	m_discrete->write(NAMCO_52XX_P_DATA(m_basenode), data & 0x0f);
88 }
89 
R2_w(uint8_t data)90 void namco_52xx_device::R2_w(uint8_t data)
91 {
92 	m_address = (m_address & 0xfff0) | ((data & 0xf) << 0);
93 }
94 
R3_w(uint8_t data)95 void namco_52xx_device::R3_w(uint8_t data)
96 {
97 	m_address = (m_address & 0xff0f) | ((data & 0xf) << 4);
98 }
99 
O_w(uint8_t data)100 void namco_52xx_device::O_w(uint8_t data)
101 {
102 	if (data & 0x10)
103 		m_address = (m_address & 0x0fff) | ((data & 0xf) << 12);
104 	else
105 		m_address = (m_address & 0xf0ff) | ((data & 0xf) << 8);
106 }
107 
108 
write(uint8_t data)109 void namco_52xx_device::write(uint8_t data)
110 {
111 	machine().scheduler().synchronize(timer_expired_delegate(FUNC(namco_52xx_device::latch_callback),this), data);
112 
113 	// TODO: should use chip_select line for this
114 	m_cpu->pulse_input_line(0, m_irq_duration);
115 }
116 
WRITE_LINE_MEMBER(namco_52xx_device::chip_select)117 WRITE_LINE_MEMBER( namco_52xx_device::chip_select )
118 {
119 	// TODO: broken sound when using this
120 	//m_cpu->set_input_line(0, state);
121 }
122 
TIMER_CALLBACK_MEMBER(namco_52xx_device::external_clock_pulse)123 TIMER_CALLBACK_MEMBER( namco_52xx_device::external_clock_pulse )
124 {
125 	m_cpu->clock_w(ASSERT_LINE);
126 	m_cpu->clock_w(CLEAR_LINE);
127 }
128 
129 
130 /***************************************************************************
131     DEVICE INTERFACE
132 ***************************************************************************/
133 
134 ROM_START( namco_52xx )
135 	ROM_REGION( 0x400, "mcu", 0 )
136 	ROM_LOAD( "52xx.bin",     0x0000, 0x0400, CRC(3257d11e) SHA1(4883b2fdbc99eb7b9906357fcc53915842c2c186) )
137 ROM_END
138 
139 
140 DEFINE_DEVICE_TYPE(NAMCO_52XX, namco_52xx_device, "namco52", "Namco 52xx")
141 
namco_52xx_device(const machine_config & mconfig,const char * tag,device_t * owner,uint32_t clock)142 namco_52xx_device::namco_52xx_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
143 	: device_t(mconfig, NAMCO_52XX, tag, owner, clock),
144 	m_cpu(*this, "mcu"),
145 	m_discrete(*this, finder_base::DUMMY_TAG),
146 	m_irq_duration(attotime::from_usec(100)),
147 	m_basenode(0),
148 	m_extclock(0),
149 	m_romread(*this),
150 	m_si(*this),
151 	m_latched_cmd(0),
152 	m_address(0)
153 {
154 }
155 
156 //-------------------------------------------------
157 //  device_start - device-specific startup
158 //-------------------------------------------------
159 
device_start()160 void namco_52xx_device::device_start()
161 {
162 	/* resolve our read/write callbacks */
163 	m_romread.resolve_safe(0);
164 	m_si.resolve_safe(0);
165 
166 	/* start the external clock */
167 	if (m_extclock != 0)
168 	{
169 		m_extclock_pulse_timer = machine().scheduler().timer_alloc(timer_expired_delegate(FUNC(namco_52xx_device::external_clock_pulse), this));
170 		m_extclock_pulse_timer->adjust(attotime(0, m_extclock), 0, attotime(0, m_extclock));
171 	}
172 
173 	save_item(NAME(m_latched_cmd));
174 	save_item(NAME(m_address));
175 }
176 
177 //-------------------------------------------------
178 // device_add_mconfig - add device configuration
179 //-------------------------------------------------
180 
device_add_mconfig(machine_config & config)181 void namco_52xx_device::device_add_mconfig(machine_config &config)
182 {
183 	MB8843(config, m_cpu, DERIVED_CLOCK(1,1));     /* parent clock, internally divided by 6 */
184 	m_cpu->read_k().set(FUNC(namco_52xx_device::K_r));
185 	m_cpu->write_o().set(FUNC(namco_52xx_device::O_w));
186 	m_cpu->write_p().set(FUNC(namco_52xx_device::P_w));
187 	m_cpu->read_si().set(FUNC(namco_52xx_device::SI_r));
188 	m_cpu->read_r<0>().set(FUNC(namco_52xx_device::R0_r));
189 	m_cpu->read_r<1>().set(FUNC(namco_52xx_device::R1_r));
190 	m_cpu->write_r<2>().set(FUNC(namco_52xx_device::R2_w));
191 	m_cpu->write_r<3>().set(FUNC(namco_52xx_device::R3_w));
192 }
193 
194 //-------------------------------------------------
195 //  device_rom_region - return a pointer to the
196 //  the device's ROM definitions
197 //-------------------------------------------------
198 
device_rom_region() const199 const tiny_rom_entry *namco_52xx_device::device_rom_region() const
200 {
201 	return ROM_NAME(namco_52xx );
202 }
203