trunk/src/emu/sound/l7a1045_l6028_dsp_a.c
r245315 | r245316 | |
1 | | /*************************************************************************** |
2 | | |
3 | | L7A1045 L6028 DSP-A |
4 | | (QFP120 package) |
5 | | |
6 | | this is the audio chip used on the following |
7 | | SNK Hyper NeoGeo 64 (arcade platform) |
8 | | AKAI MPC3000 (synth) |
9 | | |
10 | | both are driven by a V53, the MPC3000 isn't dumped. |
11 | | |
12 | | appears to write a register number and channel/voice using |
13 | | l7a1045_sound_select_w (offset 0) |
14 | | format: |
15 | | |
16 | | ---- rrrr ---c cccc |
17 | | r = register, c = channel |
18 | | |
19 | | the channel select appears to address 32 different voices (5-bits) |
20 | | the register select appears to use 4-bits with 0x0 to 0xa being valid |
21 | | |
22 | | the registers data is written / read using offsets 1,2,3 after |
23 | | setting the register + channel, this gives 3 16-bit values for |
24 | | each register. |
25 | | |
26 | | register format: |
27 | | |
28 | | offset 3 offset 2 offset 1 |
29 | | fedcba9876543210 | fedcba9876543210 | fedcba9876543210 |
30 | | |
31 | | 0 ---------------- ---------------- ---------------- |
32 | | |
33 | | 1 ---------------- ---------------- ---------------- |
34 | | |
35 | | 2 ---------------- ---------------- ---------------- |
36 | | |
37 | | 3 ---------------- ---------------- ---------------- |
38 | | |
39 | | 4 ---------------- ---------------- ---------------- |
40 | | |
41 | | 5 ---------------- ---------------- ---------------- |
42 | | |
43 | | 6 ---------------- ---------------- ---------------- |
44 | | |
45 | | 7 ---------------- ---------------- ---------------- |
46 | | |
47 | | 8 ---------------- ---------------- ---------------- (read only?) |
48 | | |
49 | | 9 ---------------- ---------------- ---------------- (read only?) |
50 | | |
51 | | a ---------------- ---------------- ---------------- |
52 | | |
53 | | Registers are not yet understood. |
54 | | |
55 | | Some of the other ports on the HNG64 sound CPU may also be tied |
56 | | to this chip, this isn't yet clear. |
57 | | |
58 | | Sample data format TBA |
59 | | |
60 | | ***************************************************************************/ |
61 | | |
62 | | #include "emu.h" |
63 | | #include "l7a1045_l6028_dsp_a.h" |
64 | | |
65 | | |
66 | | // device type definition |
67 | | const device_type L7A1045 = &device_creator<l7a1045_sound_device>; |
68 | | |
69 | | |
70 | | //************************************************************************** |
71 | | // LIVE DEVICE |
72 | | //************************************************************************** |
73 | | |
74 | | //------------------------------------------------- |
75 | | // l7a1045_sound_device - constructor |
76 | | //------------------------------------------------- |
77 | | |
78 | | l7a1045_sound_device::l7a1045_sound_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock) |
79 | | : device_t(mconfig, L7A1045, "L7A1045 L6028 DSP-A", tag, owner, clock, "l7a1045_custom", __FILE__), |
80 | | device_sound_interface(mconfig, *this), |
81 | | m_stream(NULL) |
82 | | /*m_key(0), |
83 | | m_base(NULL)*/ |
84 | | { |
85 | | } |
86 | | |
87 | | |
88 | | //------------------------------------------------- |
89 | | // device_start - device-specific startup |
90 | | //------------------------------------------------- |
91 | | |
92 | | void l7a1045_sound_device::device_start() |
93 | | { |
94 | | /* Allocate the stream */ |
95 | | m_stream = stream_alloc(0, 2, clock() / 384); |
96 | | } |
97 | | |
98 | | |
99 | | //------------------------------------------------- |
100 | | // sound_stream_update - handle a stream update |
101 | | //------------------------------------------------- |
102 | | |
103 | | void l7a1045_sound_device::sound_stream_update(sound_stream &stream, stream_sample_t **inputs, stream_sample_t **outputs, int samples) |
104 | | { |
105 | | /* Clear the buffers */ |
106 | | memset(outputs[0], 0, samples*sizeof(*outputs[0])); |
107 | | memset(outputs[1], 0, samples*sizeof(*outputs[1])); |
108 | | } |
109 | | |
110 | | |
111 | | WRITE16_MEMBER( l7a1045_sound_device::l7a1045_sound_w ) |
112 | | { |
113 | | m_stream->update(); |
114 | | |
115 | | switch (offset) |
116 | | { |
117 | | case 0x00:l7a1045_sound_select_w(space, offset, data, mem_mask); break; |
118 | | case 0x01:l7a1045_sound_data_02_w(space, offset, data, mem_mask); break; |
119 | | case 0x02:l7a1045_sound_data_04_w(space, offset, data, mem_mask); break; |
120 | | case 0x03:l7a1045_sound_data_06_w(space, offset, data, mem_mask); break; |
121 | | } |
122 | | |
123 | | } |
124 | | |
125 | | |
126 | | READ16_MEMBER( l7a1045_sound_device::l7a1045_sound_r ) |
127 | | { |
128 | | m_stream->update(); |
129 | | |
130 | | switch (offset) |
131 | | { |
132 | | case 0x00: |
133 | | case 0x01: |
134 | | printf("%08x: l7a1045_sound_r unknown offset %02x\n", space.device().safe_pc(), offset * 2); |
135 | | return 0x0000; |
136 | | |
137 | | case 0x02: return l7a1045_sound_port_0004_r(space, offset, mem_mask); |
138 | | case 0x03: return l7a1045_sound_port_0006_r(space, offset, mem_mask); |
139 | | } |
140 | | return 0x000; |
141 | | } |
142 | | |
143 | | |
144 | | WRITE16_MEMBER(l7a1045_sound_device::l7a1045_sound_select_w) |
145 | | { |
146 | | // I'm guessing these addresses are the sound chip / DSP? |
147 | | |
148 | | // ---- ---- 000c cccc |
149 | | // c = channel |
150 | | |
151 | | if (data & 0x00e0) printf("%08x: l7a1045_sound_select_w unknown channel %02x\n", space.device().safe_pc(), data & 0x00ff); |
152 | | |
153 | | UINT8 command = data >> 8; |
154 | | |
155 | | switch (command) |
156 | | { |
157 | | case 0x00: |
158 | | case 0x01: |
159 | | case 0x02: |
160 | | case 0x03: // 00003fffffff (startup only?) |
161 | | case 0x04: // doesn't use 6 |
162 | | case 0x05: // 00003fffffff (mostly, often) |
163 | | case 0x06: // 00007ff0ffff mostly |
164 | | case 0x07: // 0000000f0708 etc. (low values) |
165 | | case 0x08: // doesn't write to 2/4/6 with this set?? |
166 | | case 0x09: // doesn't write to 2/4/6 with this set?? |
167 | | case 0x0a: // random looking values |
168 | | |
169 | | break; |
170 | | |
171 | | default: |
172 | | printf("%08x: l7a1045_sound_select_w unrecognized command %02x\n", space.device().safe_pc(), command); |
173 | | break; |
174 | | } |
175 | | |
176 | | COMBINE_DATA(&m_audiochannel); |
177 | | } |
178 | | |
179 | | WRITE16_MEMBER(l7a1045_sound_device::l7a1045_sound_data_02_w) |
180 | | { |
181 | | m_audiodat[m_audiochannel].dat[2] = data; |
182 | | |
183 | | // if ((m_audiochannel & 0xff00) == 0x0a00) |
184 | | // printf("%08x: write port 0x0002 chansel %04x data %04x (%04x%04x%04x)\n", space.device().safe_pc(), m_audiochannel, data, m_audiodat[m_audiochannel].dat[0], m_audiodat[m_audiochannel].dat[1], m_audiodat[m_audiochannel].dat[2]); |
185 | | } |
186 | | |
187 | | WRITE16_MEMBER(l7a1045_sound_device::l7a1045_sound_data_04_w) |
188 | | { |
189 | | m_audiodat[m_audiochannel].dat[1] = data; |
190 | | |
191 | | // if ((m_audiochannel & 0xff00) == 0x0a00) |
192 | | // printf("%08x: write port 0x0004 chansel %04x data %04x (%04x%04x%04x)\n", space.device().safe_pc(), m_audiochannel, data, m_audiodat[m_audiochannel].dat[0], m_audiodat[m_audiochannel].dat[1], m_audiodat[m_audiochannel].dat[2]); |
193 | | } |
194 | | WRITE16_MEMBER(l7a1045_sound_device::l7a1045_sound_data_06_w) |
195 | | { |
196 | | m_audiodat[m_audiochannel].dat[0] = data; |
197 | | |
198 | | // if ((m_audiochannel & 0xff00) == 0x0a00) |
199 | | // printf("%08x: write port 0x0006 chansel %04x data %04x (%04x%04x%04x)\n", space.device().safe_pc(), m_audiochannel, data, m_audiodat[m_audiochannel].dat[0], m_audiodat[m_audiochannel].dat[1], m_audiodat[m_audiochannel].dat[2]); |
200 | | } |
201 | | |
202 | | |
203 | | READ16_MEMBER(l7a1045_sound_device::l7a1045_sound_port_0004_r) |
204 | | { |
205 | | // it writes the channel select before reading this.. so either it works on channels, or the command.. |
206 | | // read in irq5 |
207 | | printf("%08x: l7a1045_sound_port_0004_r mask (%04x) chn %04x\n", space.device().safe_pc(), mem_mask, m_audiochannel); |
208 | | return rand(); |
209 | | } |
210 | | |
211 | | READ16_MEMBER(l7a1045_sound_device::l7a1045_sound_port_0006_r) |
212 | | { |
213 | | // it writes the channel select before reading this.. so either it works on channels, or the command.. |
214 | | // read in irq5 |
215 | | printf("%08x: l7a1045_sound_port_0006_r mask (%04x) chn %04x\n", space.device().safe_pc(), mem_mask, m_audiochannel); |
216 | | return rand(); |
217 | | } |
trunk/src/emu/sound/l7a1045_l6028_dsp_a.h
r245315 | r245316 | |
1 | | //************************************************************************** |
2 | | // TYPE DEFINITIONS |
3 | | //************************************************************************** |
4 | | |
5 | | struct l7a1045_voice |
6 | | { |
7 | | /* |
8 | | l7a1045_voice() : |
9 | | pos(0), |
10 | | frac(0) |
11 | | { |
12 | | memset(regs, 0, sizeof(UINT32)*8); |
13 | | } |
14 | | |
15 | | UINT32 regs[8]; |
16 | | UINT32 pos; |
17 | | UINT32 frac; |
18 | | */ |
19 | | }; |
20 | | |
21 | | // ======================> l7a1045_sound_device |
22 | | |
23 | | class l7a1045_sound_device : public device_t, |
24 | | public device_sound_interface |
25 | | { |
26 | | public: |
27 | | l7a1045_sound_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock); |
28 | | ~l7a1045_sound_device() { } |
29 | | |
30 | | // void set_base(INT8* base) { m_base = base; } |
31 | | |
32 | | DECLARE_WRITE16_MEMBER( l7a1045_sound_w ); |
33 | | DECLARE_READ16_MEMBER( l7a1045_sound_r ); |
34 | | |
35 | | protected: |
36 | | // device-level overrides |
37 | | virtual void device_start(); |
38 | | |
39 | | // sound stream update overrides |
40 | | virtual void sound_stream_update(sound_stream &stream, stream_sample_t **inputs, stream_sample_t **outputs, int samples); |
41 | | |
42 | | private: |
43 | | sound_stream *m_stream; |
44 | | // l7a1045_voice m_voice[32]; |
45 | | // UINT16 m_key; |
46 | | // INT8* m_base; |
47 | | |
48 | | UINT16 m_audiochannel; |
49 | | |
50 | | struct l7a1045_48bit_data { |
51 | | UINT16 dat[3]; |
52 | | }; |
53 | | |
54 | | l7a1045_48bit_data m_audiodat[0x10000]; |
55 | | |
56 | | DECLARE_WRITE16_MEMBER(l7a1045_sound_select_w); |
57 | | DECLARE_WRITE16_MEMBER(l7a1045_sound_data_02_w); |
58 | | DECLARE_WRITE16_MEMBER(l7a1045_sound_data_04_w); |
59 | | DECLARE_WRITE16_MEMBER(l7a1045_sound_data_06_w); |
60 | | |
61 | | DECLARE_READ16_MEMBER(l7a1045_sound_port_0004_r); |
62 | | DECLARE_READ16_MEMBER(l7a1045_sound_port_0006_r); |
63 | | |
64 | | |
65 | | }; |
66 | | |
67 | | extern const device_type L7A1045; |
trunk/src/mame/audio/hng64.c
r245315 | r245316 | |
200 | 200 | |
201 | 201 | } |
202 | 202 | |
| 203 | READ16_MEMBER(hng64_state::hng64_sound_port_0004_r) |
| 204 | { |
| 205 | // it writes the channel select before reading this.. so either it works on channels, or the command.. |
| 206 | // read in irq5 |
| 207 | printf("%08x: hng64_sound_port_0004_r mask (%04x) chn %04x\n", space.device().safe_pc(), mem_mask, m_audiochannel); |
| 208 | return rand(); |
| 209 | } |
203 | 210 | |
| 211 | READ16_MEMBER(hng64_state::hng64_sound_port_0006_r) |
| 212 | { |
| 213 | // it writes the channel select before reading this.. so either it works on channels, or the command.. |
| 214 | // read in irq5 |
| 215 | printf("%08x: hng64_sound_port_0006_r mask (%04x) chn %04x\n", space.device().safe_pc(), mem_mask, m_audiochannel); |
| 216 | return rand(); |
| 217 | } |
| 218 | |
204 | 219 | READ16_MEMBER(hng64_state::hng64_sound_port_0008_r) |
205 | 220 | { |
206 | 221 | // read in irq5 |
r245315 | r245316 | |
208 | 223 | return rand(); |
209 | 224 | } |
210 | 225 | |
| 226 | WRITE16_MEMBER(hng64_state::hng64_sound_select_w) |
| 227 | { |
| 228 | // I'm guessing these addresses are the sound chip / DSP? |
211 | 229 | |
| 230 | // ---- ---- 000c cccc |
| 231 | // c = channel |
212 | 232 | |
| 233 | if (data & 0x00e0) printf("hng64_sound_select_w unknown channel %02x\n", data & 0x00ff); |
| 234 | |
| 235 | UINT8 command = data >> 8; |
| 236 | |
| 237 | switch (command) |
| 238 | { |
| 239 | case 0x00: |
| 240 | case 0x01: |
| 241 | case 0x02: |
| 242 | case 0x03: // 00003fffffff (startup only?) |
| 243 | case 0x04: // doesn't use 6 |
| 244 | case 0x05: // 00003fffffff (mostly, often) |
| 245 | case 0x06: // 00007ff0ffff mostly |
| 246 | case 0x07: // 0000000f0708 etc. (low values) |
| 247 | case 0x08: // doesn't write to 2/4/6 with this set?? |
| 248 | case 0x09: // doesn't write to 2/4/6 with this set?? |
| 249 | case 0x0a: // random looking values |
| 250 | |
| 251 | break; |
| 252 | |
| 253 | default: |
| 254 | printf("hng64_sound_select_w unrecognized command %02x\n", command); |
| 255 | break; |
| 256 | } |
| 257 | |
| 258 | COMBINE_DATA(&m_audiochannel); |
| 259 | } |
| 260 | |
| 261 | WRITE16_MEMBER(hng64_state::hng64_sound_data_02_w) |
| 262 | { |
| 263 | m_audiodat[m_audiochannel].dat[2] = data; |
| 264 | |
| 265 | // if ((m_audiochannel & 0xff00) == 0x0a00) |
| 266 | // printf("write port 0x0002 chansel %04x data %04x (%04x%04x%04x)\n", m_audiochannel, data, m_audiodat[m_audiochannel].dat[0], m_audiodat[m_audiochannel].dat[1], m_audiodat[m_audiochannel].dat[2]); |
| 267 | } |
| 268 | |
| 269 | WRITE16_MEMBER(hng64_state::hng64_sound_data_04_w) |
| 270 | { |
| 271 | m_audiodat[m_audiochannel].dat[1] = data; |
| 272 | |
| 273 | // if ((m_audiochannel & 0xff00) == 0x0a00) |
| 274 | // printf("write port 0x0004 chansel %04x data %04x (%04x%04x%04x)\n", m_audiochannel, data, m_audiodat[m_audiochannel].dat[0], m_audiodat[m_audiochannel].dat[1], m_audiodat[m_audiochannel].dat[2]); |
| 275 | } |
| 276 | WRITE16_MEMBER(hng64_state::hng64_sound_data_06_w) |
| 277 | { |
| 278 | m_audiodat[m_audiochannel].dat[0] = data; |
| 279 | |
| 280 | // if ((m_audiochannel & 0xff00) == 0x0a00) |
| 281 | // printf("write port 0x0006 chansel %04x data %04x (%04x%04x%04x)\n", m_audiochannel, data, m_audiodat[m_audiochannel].dat[0], m_audiodat[m_audiochannel].dat[1], m_audiodat[m_audiochannel].dat[2]); |
| 282 | } |
| 283 | |
213 | 284 | // but why not just use the V33/V53 XA mode?? |
214 | 285 | WRITE16_MEMBER(hng64_state::hng64_sound_bank_w) |
215 | 286 | { |
r245315 | r245316 | |
295 | 366 | } |
296 | 367 | |
297 | 368 | static ADDRESS_MAP_START( hng_sound_io, AS_IO, 16, hng64_state ) |
298 | | AM_RANGE(0x0000, 0x0007) AM_DEVREADWRITE("l7a1045", l7a1045_sound_device, l7a1045_sound_r, l7a1045_sound_w ) |
299 | | |
| 369 | AM_RANGE(0x0000, 0x0001) AM_WRITE( hng64_sound_select_w ) |
| 370 | AM_RANGE(0x0002, 0x0003) AM_WRITE( hng64_sound_data_02_w ) |
| 371 | AM_RANGE(0x0004, 0x0005) AM_READWRITE( hng64_sound_port_0004_r, hng64_sound_data_04_w ) |
| 372 | AM_RANGE(0x0006, 0x0007) AM_READWRITE( hng64_sound_port_0006_r, hng64_sound_data_06_w ) |
300 | 373 | AM_RANGE(0x0008, 0x0009) AM_READWRITE( hng64_sound_port_0008_r, hng64_sound_port_0008_w ) |
301 | 374 | AM_RANGE(0x000a, 0x000b) AM_WRITE( hng64_sound_port_000a_w ) |
302 | 375 | AM_RANGE(0x000c, 0x000d) AM_WRITE( hng64_sound_port_000c_w ) |
r245315 | r245316 | |
371 | 444 | MCFG_V53_TCU_OUT1_HANDLER(WRITELINE(hng64_state, tcu_tm1_cb)) |
372 | 445 | MCFG_V53_TCU_OUT2_HANDLER(WRITELINE(hng64_state, tcu_tm2_cb)) |
373 | 446 | |
374 | | MCFG_SOUND_ADD("l7a1045", L7A1045, 16000000 ) // ?? |
375 | | MCFG_SOUND_ROUTE(1, "lspeaker", 1.0) |
376 | | MCFG_SOUND_ROUTE(0, "rspeaker", 1.0) |
377 | | |
378 | 447 | MACHINE_CONFIG_END |