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