1 // license:BSD-3-Clause
2 // copyright-holders:Aaron Giles
3 /***************************************************************************
4 
5     atarisac.cpp
6 
7     Functions to emulate the Atari "SAC" audio board
8 
9 ***************************************************************************/
10 
11 #include "emu.h"
12 #include "audio/atarisac.h"
13 
14 #include "cpu/m68000/m68000.h"
15 
16 
17 //**************************************************************************
18 //  GLOBAL VARIABLES
19 //**************************************************************************
20 
21 DEFINE_DEVICE_TYPE(ATARI_SAC, atari_sac_device, "atarisac", "Atari SAC Sound Board")
22 
23 
24 
25 //**************************************************************************
26 //  MEMORY MAPS
27 //**************************************************************************
28 
29 /*************************************
30  *
31  *  Sound CPU memory handlers
32  *
33  *************************************/
34 
sac_6502_map(address_map & map)35 void atari_sac_device::sac_6502_map(address_map &map)
36 {
37 	map(0x0000, 0x1fff).ram();
38 	map(0x2000, 0x2001).mirror(0x7fe).rw(m_ym2151, FUNC(ym2151_device::read), FUNC(ym2151_device::write));
39 	map(0x2800, 0x2800).mirror(0x3f9).w(m_datin, FUNC(generic_latch_8_device::write));
40 	map(0x2802, 0x2802).mirror(0x3f9).rw(FUNC(atari_sac_device::sound_irq_ack_r), FUNC(atari_sac_device::sound_irq_ack_w));
41 	map(0x2804, 0x2804).mirror(0x3f9).w(m_soundcomm, FUNC(atari_sound_comm_device::sound_response_w));
42 	map(0x2806, 0x2806).mirror(0x3f9).w(FUNC(atari_sac_device::wrio_w));
43 	map(0x2c00, 0x2c00).mirror(0x3f9).r(m_soundcomm, FUNC(atari_sound_comm_device::sound_command_r));
44 	map(0x2c02, 0x2c02).mirror(0x3f9).r(FUNC(atari_sac_device::rdio_r));
45 	map(0x2c04, 0x2c04).mirror(0x3f9).r(m_datout, FUNC(generic_latch_8_device::read));
46 	map(0x2c06, 0x2c06).mirror(0x3f9).r(FUNC(atari_sac_device::pstat_r));
47 	map(0x3000, 0x3fff).bankr("cpubank");
48 	map(0x4000, 0xffff).rom();
49 }
50 
51 
52 /*************************************
53  *
54  *  68000 Sound CPU memory handlers
55  *
56  *************************************/
57 
sac_68k_map(address_map & map)58 void atari_sac_device::sac_68k_map(address_map &map)
59 {
60 	map.global_mask(0x87ffff);
61 	map(0x000000, 0x03ffff).rom();
62 	map(0x860000, 0x860001).mirror(0x187fe).r(FUNC(atari_sac_device::rdp8_r));
63 	map(0x860800, 0x860800).mirror(0x187fe).w(m_datout, FUNC(generic_latch_8_device::write));
64 	map(0x861000, 0x861000).mirror(0x187fe).w(m_datin, FUNC(generic_latch_8_device::acknowledge_w));
65 	map(0x861800, 0x861801).mirror(0x187ee).select(0x10).w(FUNC(atari_sac_device::dac_w));
66 	map(0x864000, 0x867fff).mirror(0x18000).ram(); // 8Kx8x2
67 }
68 
69 
70 
71 //**************************************************************************
72 //  I/O PORT DEFINITIONS
73 //**************************************************************************
74 
75 INPUT_PORTS_START( sac_ioports )
76 	PORT_START("SAC")
77 	PORT_BIT( 0x01, IP_ACTIVE_HIGH, IPT_COIN2 )
78 	PORT_BIT( 0x02, IP_ACTIVE_HIGH, IPT_COIN1 )
79 	PORT_BIT( 0x04, IP_ACTIVE_HIGH, IPT_COIN4 )
80 	PORT_BIT( 0x08, IP_ACTIVE_HIGH, IPT_COIN3 )
81 	PORT_BIT( 0x10, IP_ACTIVE_HIGH, IPT_UNUSED )
82 	PORT_BIT( 0x20, IP_ACTIVE_HIGH, IPT_CUSTOM ) PORT_READ_LINE_DEVICE_MEMBER("soundcomm", atari_sound_comm_device, sound_to_main_ready) // output buffer full
83 	PORT_BIT( 0x40, IP_ACTIVE_LOW, IPT_CUSTOM ) PORT_READ_LINE_DEVICE_MEMBER("soundcomm", atari_sound_comm_device, main_to_sound_ready) // input buffer full
PORT_READ_LINE_DEVICE_MEMBER(DEVICE_SELF,atari_sac_device,main_test_read_line)84 	PORT_BIT( 0x80, IP_ACTIVE_HIGH, IPT_CUSTOM ) PORT_READ_LINE_DEVICE_MEMBER(DEVICE_SELF, atari_sac_device, main_test_read_line) // self test
85 INPUT_PORTS_END
86 
87 
88 
89 //**************************************************************************
90 //  SAC-SPECIFIC IMPLEMENTATION
91 //**************************************************************************
92 
93 //-------------------------------------------------
94 //  atari_sac_device: Constructor
95 //-------------------------------------------------
96 
97 atari_sac_device::atari_sac_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock)
98 	: atari_jsa_base_device(mconfig, ATARI_SAC, tag, owner, clock, 2)
99 	, m_daccpu(*this, "dac")
100 	, m_datin(*this, "datin")
101 	, m_datout(*this, "datout")
102 	, m_rdac(*this, "rdac")
103 	, m_ldac(*this, "ldac")
104 	, m_inputs(*this, "SAC")
105 	, m_68k_reset(false)
106 	, m_10k_int(false)
107 {
108 }
109 
110 
111 //-------------------------------------------------
112 //  rdio_r: Handle reads from the general I/O
113 //  port on a SAC board
114 //-------------------------------------------------
115 
rdio_r()116 u8 atari_sac_device::rdio_r()
117 {
118 	//
119 	//  0x80 = self test
120 	//  0x40 = NMI line state (active low)
121 	//  0x20 = sound output full
122 	//  0x10 = +5V
123 	//  0x08 = coin 4
124 	//  0x04 = coin 3
125 	//  0x02 = coin 2
126 	//  0x01 = coin 1
127 	//
128 
129 	u8 result = m_inputs->read();
130 	if (!m_test_read_cb())
131 		result ^= 0x80;
132 
133 	return result;
134 }
135 
136 
137 //-------------------------------------------------
138 //  wrio_w: Handle writes to the general I/O
139 //  port on a SAC board
140 //-------------------------------------------------
141 
wrio_w(u8 data)142 void atari_sac_device::wrio_w(u8 data)
143 {
144 	//
145 	//  0xc0 = bank address
146 	//  0x20 = coin counter 2
147 	//  0x10 = coin counter 1
148 	//  0x08 = 68K reset (active low)
149 	//  0x06 = not used
150 	//  0x01 = YM2151 reset (active low)
151 	//
152 
153 	// update the bank
154 	m_cpu_bank->set_entry(BIT(data, 6, 2));
155 
156 	// coin counters
157 	machine().bookkeeping().coin_counter_w(1, BIT(data, 5));
158 	machine().bookkeeping().coin_counter_w(0, BIT(data, 4));
159 
160 	// reset the 68K
161 	m_68k_reset = !BIT(data, 3);
162 	m_daccpu->set_input_line(INPUT_LINE_RESET, BIT(data, 3) ? CLEAR_LINE : ASSERT_LINE);
163 
164 	// reset the YM2151
165 	m_ym2151->reset_w(BIT(data, 0));
166 }
167 
168 
169 //-------------------------------------------------
170 //  pstat_r: Check internal communications status
171 //  from the 6502 side
172 //-------------------------------------------------
173 
pstat_r()174 u8 atari_sac_device::pstat_r()
175 {
176 	int temp = 0xff;
177 	if (m_datin->pending_r()) temp ^= 0x80;
178 	if (m_datout->pending_r()) temp ^= 0x40;
179 	if (m_68k_reset) temp ^= 0x20;
180 	return temp;
181 }
182 
183 
184 //-------------------------------------------------
185 //  int_10k_gen: Generate 10kHz interrupt for
186 //  driving the DAC
187 //-------------------------------------------------
188 
INTERRUPT_GEN_MEMBER(atari_sac_device::int_10k_gen)189 INTERRUPT_GEN_MEMBER(atari_sac_device::int_10k_gen)
190 {
191 	if (!m_10k_int)
192 	{
193 		m_10k_int = true;
194 		m_daccpu->set_input_line(M68K_IRQ_6, ASSERT_LINE);
195 	}
196 }
197 
198 
199 //-------------------------------------------------
200 //  rdp8_r: Read data sent by the 6502 and check
201 //  communications status
202 //-------------------------------------------------
203 
rdp8_r()204 u16 atari_sac_device::rdp8_r()
205 {
206 	int temp = (m_datin->read() << 8) | 0xff;
207 
208 	if (m_datin->pending_r()) temp ^= 0x08;
209 	if (m_datout->pending_r()) temp ^= 0x04;
210 	return temp;
211 }
212 
213 
214 //-------------------------------------------------
215 //  dac_w: Write a sample to one of the DAC
216 //  channels
217 //-------------------------------------------------
218 
dac_w(offs_t offset,u16 data)219 void atari_sac_device::dac_w(offs_t offset, u16 data)
220 {
221 	//int clip = BIT(data, 15);
222 	//int off0b = BIT(data, 13) | BIT(data, 14);
223 	//int off4b = BIT(data, 13) & BIT(data, 14);
224 	u16 sample = ((data >> 3) & 0x800) | ((data >> 2) & 0x7ff);
225 
226 	if (offset & 8)
227 		m_ldac->write(sample);
228 	else
229 		m_rdac->write(sample);
230 
231 	if (m_10k_int)
232 	{
233 		m_10k_int = false;
234 		m_daccpu->set_input_line(M68K_IRQ_6, CLEAR_LINE);
235 	}
236 }
237 
238 
239 //-------------------------------------------------
240 //  device_add_mconfig - add device configuration
241 //-------------------------------------------------
242 
device_add_mconfig(machine_config & config)243 void atari_sac_device::device_add_mconfig(machine_config &config)
244 {
245 	// basic machine hardware
246 	M6502(config, m_jsacpu, 14.318181_MHz_XTAL/8);
247 	m_jsacpu->set_addrmap(AS_PROGRAM, &atari_sac_device::sac_6502_map);
248 	m_jsacpu->set_periodic_int(FUNC(atari_sac_device::sound_irq_gen), attotime::from_hz(14.318181_MHz_XTAL/4/4/16/16/14));
249 
250 	M68000(config, m_daccpu, 14.318181_MHz_XTAL/2);
251 	m_daccpu->set_addrmap(AS_PROGRAM, &atari_sac_device::sac_68k_map);
252 	m_daccpu->set_periodic_int(FUNC(atari_sac_device::int_10k_gen), attotime::from_hz(10000));
253 	// TODO: determine exact frequency (controlled by a PAL16R4)
254 
255 	GENERIC_LATCH_8(config, m_datin);
256 	m_datin->data_pending_callback().set_inputline(m_daccpu, M68K_IRQ_2);
257 	m_datin->set_separate_acknowledge(true);
258 
259 	GENERIC_LATCH_8(config, m_datout);
260 
261 	// sound hardware
262 	ATARI_SOUND_COMM(config, m_soundcomm, m_jsacpu)
263 		.int_callback().set(FUNC(atari_sac_device::main_int_write_line));
264 
265 	YM2151(config, m_ym2151, 14.318181_MHz_XTAL/4);
266 	m_ym2151->irq_handler().set(FUNC(atari_sac_device::ym2151_irq_gen));
267 	m_ym2151->port_write_handler().set(FUNC(atari_sac_device::ym2151_port_w));
268 	m_ym2151->add_route(0, *this, 0.60, AUTO_ALLOC_INPUT, 0);
269 	m_ym2151->add_route(1, *this, 0.60, AUTO_ALLOC_INPUT, 1);
270 
271 	// FIXME: there is actually only one DAC (plus some analog switches)
272 	AM6012(config, m_rdac).add_route(ALL_OUTPUTS, *this, 0.5, AUTO_ALLOC_INPUT, 1); // AM6012.6j
273 	AM6012(config, m_ldac).add_route(ALL_OUTPUTS, *this, 0.5, AUTO_ALLOC_INPUT, 0); // AM6012.6j
274 }
275 
276 
277 //-------------------------------------------------
278 //  device_input_ports - return a pointer to
279 //  the device's I/O ports
280 //-------------------------------------------------
281 
device_input_ports() const282 ioport_constructor atari_sac_device::device_input_ports() const
283 {
284 	return INPUT_PORTS_NAME( sac_ioports );
285 }
286 
287 
288 //-------------------------------------------------
289 //  device_start: Start up the device
290 //-------------------------------------------------
291 
device_start()292 void atari_sac_device::device_start()
293 {
294 	// call the parent
295 	atari_jsa_base_device::device_start();
296 
297 	// save states
298 	save_item(NAME(m_68k_reset));
299 	save_item(NAME(m_10k_int));
300 }
301 
302 
303 //-------------------------------------------------
304 //  device_reset: Reset the device
305 //-------------------------------------------------
306 
device_reset()307 void atari_sac_device::device_reset()
308 {
309 	// call the parent
310 	atari_jsa_base_device::device_reset();
311 
312 	// hold 68K in reset
313 	m_68k_reset = true;
314 	m_daccpu->set_input_line(INPUT_LINE_RESET, ASSERT_LINE);
315 }
316 
317 
318 //-------------------------------------------------
319 //  update_all_volumes: Update volumes for all
320 //  chips
321 //-------------------------------------------------
322 
update_all_volumes()323 void atari_sac_device::update_all_volumes()
324 {
325 	// TODO: CT1 and CT2 control LPFs on left and right channels
326 }
327