1 // license:BSD-3-Clause
2 // copyright-holders:Juergen Buchmueller, Manuel Abadia
3 /***************************************************************************
4
5 Philips SAA1099 Sound driver
6
7 By Juergen Buchmueller and Manuel Abadia
8
9 SAA1099 register layout:
10 ========================
11
12 offs | 7654 3210 | description
13 -----+-----------+---------------------------
14 0x00 | ---- xxxx | Amplitude channel 0 (left)
15 0x00 | xxxx ---- | Amplitude channel 0 (right)
16 0x01 | ---- xxxx | Amplitude channel 1 (left)
17 0x01 | xxxx ---- | Amplitude channel 1 (right)
18 0x02 | ---- xxxx | Amplitude channel 2 (left)
19 0x02 | xxxx ---- | Amplitude channel 2 (right)
20 0x03 | ---- xxxx | Amplitude channel 3 (left)
21 0x03 | xxxx ---- | Amplitude channel 3 (right)
22 0x04 | ---- xxxx | Amplitude channel 4 (left)
23 0x04 | xxxx ---- | Amplitude channel 4 (right)
24 0x05 | ---- xxxx | Amplitude channel 5 (left)
25 0x05 | xxxx ---- | Amplitude channel 5 (right)
26 | |
27 0x08 | xxxx xxxx | Frequency channel 0
28 0x09 | xxxx xxxx | Frequency channel 1
29 0x0a | xxxx xxxx | Frequency channel 2
30 0x0b | xxxx xxxx | Frequency channel 3
31 0x0c | xxxx xxxx | Frequency channel 4
32 0x0d | xxxx xxxx | Frequency channel 5
33 | |
34 0x10 | ---- -xxx | Channel 0 octave select
35 0x10 | -xxx ---- | Channel 1 octave select
36 0x11 | ---- -xxx | Channel 2 octave select
37 0x11 | -xxx ---- | Channel 3 octave select
38 0x12 | ---- -xxx | Channel 4 octave select
39 0x12 | -xxx ---- | Channel 5 octave select
40 | |
41 0x14 | ---- ---x | Channel 0 frequency enable (0 = off, 1 = on)
42 0x14 | ---- --x- | Channel 1 frequency enable (0 = off, 1 = on)
43 0x14 | ---- -x-- | Channel 2 frequency enable (0 = off, 1 = on)
44 0x14 | ---- x--- | Channel 3 frequency enable (0 = off, 1 = on)
45 0x14 | ---x ---- | Channel 4 frequency enable (0 = off, 1 = on)
46 0x14 | --x- ---- | Channel 5 frequency enable (0 = off, 1 = on)
47 | |
48 0x15 | ---- ---x | Channel 0 noise enable (0 = off, 1 = on)
49 0x15 | ---- --x- | Channel 1 noise enable (0 = off, 1 = on)
50 0x15 | ---- -x-- | Channel 2 noise enable (0 = off, 1 = on)
51 0x15 | ---- x--- | Channel 3 noise enable (0 = off, 1 = on)
52 0x15 | ---x ---- | Channel 4 noise enable (0 = off, 1 = on)
53 0x15 | --x- ---- | Channel 5 noise enable (0 = off, 1 = on)
54 | |
55 0x16 | ---- --xx | Noise generator parameters 0
56 0x16 | --xx ---- | Noise generator parameters 1
57 | |
58 0x18 | --xx xxxx | Envelope generator 0 parameters
59 0x18 | x--- ---- | Envelope generator 0 control enable (0 = off, 1 = on)
60 0x19 | --xx xxxx | Envelope generator 1 parameters
61 0x19 | x--- ---- | Envelope generator 1 control enable (0 = off, 1 = on)
62 | |
63 0x1c | ---- ---x | All channels enable (0 = off, 1 = on)
64 0x1c | ---- --x- | Synch & Reset generators
65
66 Unspecified bits should be written as zero.
67
68 ***************************************************************************/
69
70 #include "emu.h"
71 #include "saa1099.h"
72
73 #define LEFT 0x00
74 #define RIGHT 0x01
75
76 static const int amplitude_lookup[16] = {
77 0*32767/16, 1*32767/16, 2*32767/16, 3*32767/16,
78 4*32767/16, 5*32767/16, 6*32767/16, 7*32767/16,
79 8*32767/16, 9*32767/16, 10*32767/16, 11*32767/16,
80 12*32767/16, 13*32767/16, 14*32767/16, 15*32767/16
81 };
82
83 static const uint8_t envelope[8][64] = {
84 /* zero amplitude */
85 { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
86 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
87 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
88 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
89 /* maximum amplitude */
90 {15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
91 15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
92 15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
93 15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15, },
94 /* single decay */
95 {15,14,13,12,11,10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0,
96 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
97 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
98 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
99 /* repetitive decay */
100 {15,14,13,12,11,10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0,
101 15,14,13,12,11,10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0,
102 15,14,13,12,11,10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0,
103 15,14,13,12,11,10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0 },
104 /* single triangular */
105 { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9,10,11,12,13,14,15,
106 15,14,13,12,11,10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0,
107 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
108 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
109 /* repetitive triangular */
110 { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9,10,11,12,13,14,15,
111 15,14,13,12,11,10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0,
112 0, 1, 2, 3, 4, 5, 6, 7, 8, 9,10,11,12,13,14,15,
113 15,14,13,12,11,10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0 },
114 /* single attack */
115 { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9,10,11,12,13,14,15,
116 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
117 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
118 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
119 /* repetitive attack */
120 { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9,10,11,12,13,14,15,
121 0, 1, 2, 3, 4, 5, 6, 7, 8, 9,10,11,12,13,14,15,
122 0, 1, 2, 3, 4, 5, 6, 7, 8, 9,10,11,12,13,14,15,
123 0, 1, 2, 3, 4, 5, 6, 7, 8, 9,10,11,12,13,14,15 }
124 };
125
126
127 // device type definition
128 //DEFINE_DEVICE_TYPE(SAA1099, saa1099_device, "saa1099", "Philips SAA1099")
129 #define SAA1099 1
130
131 //**************************************************************************
132 // LIVE DEVICE
133 //**************************************************************************
134
135 //-------------------------------------------------
136 // saa1099_device - constructor
137 //-------------------------------------------------
138
139 #define FILL_ARRAY( _FILL_ ) memset( _FILL_, 0, sizeof( _FILL_ ) )
140
saa1099_device(const machine_config & mconfig,const char * tag,device_t * owner,uint32_t clock)141 saa1099_device::saa1099_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
142 : device_t(mconfig, SAA1099, tag, owner, clock)
143 , device_sound_interface(mconfig, *this)
144 , m_stream(0)
145 #if 0
146 , m_noise_params{ 0, 0 }
147 , m_env_enable{ 0, 0 }
148 , m_env_reverse_right{ 0, 0 }
149 , m_env_mode{ 0, 0 }
150 , m_env_bits{ 0, 0 }
151 , m_env_clock{ 0, 0 }
152 , m_env_step{ 0, 0 }
153 #endif
154 , m_all_ch_enable(0)
155 , m_sync_state(0)
156 , m_selected_reg(0)
157 , m_sample_rate(0.0)
158 {
159 FILL_ARRAY( m_noise_params );
160 FILL_ARRAY( m_env_enable );
161 FILL_ARRAY( m_env_reverse_right );
162 FILL_ARRAY( m_env_mode );
163 FILL_ARRAY( m_env_bits );
164 FILL_ARRAY( m_env_clock );
165 FILL_ARRAY( m_env_step );
166
167 }
168
169
170 //-------------------------------------------------
171 // device_start - device-specific startup
172 //-------------------------------------------------
173
device_start()174 void saa1099_device::device_start()
175 {
176 /* copy global parameters */
177 m_master_clock = clock();
178 m_sample_rate = clock() / 256;
179
180 /* for each chip allocate one stream */
181 m_stream = stream_alloc(0, 2, m_sample_rate);
182
183 save_item(NAME(m_noise_params));
184 save_item(NAME(m_env_enable));
185 save_item(NAME(m_env_reverse_right));
186 save_item(NAME(m_env_mode));
187 save_item(NAME(m_env_bits));
188 save_item(NAME(m_env_clock));
189 save_item(NAME(m_env_step));
190 save_item(NAME(m_all_ch_enable));
191 save_item(NAME(m_sync_state));
192 save_item(NAME(m_selected_reg));
193
194 for (int i = 0; i < 6; i++)
195 {
196 save_item(NAME(m_channels[i].frequency), i);
197 save_item(NAME(m_channels[i].freq_enable), i);
198 save_item(NAME(m_channels[i].noise_enable), i);
199 save_item(NAME(m_channels[i].octave), i);
200 save_item(NAME(m_channels[i].amplitude), i);
201 save_item(NAME(m_channels[i].envelope), i);
202 save_item(NAME(m_channels[i].counter), i);
203 save_item(NAME(m_channels[i].freq), i);
204 save_item(NAME(m_channels[i].level), i);
205 }
206
207 for (int i = 0; i < 2; i++)
208 {
209 save_item(NAME(m_noise[i].counter), i);
210 save_item(NAME(m_noise[i].freq), i);
211 save_item(NAME(m_noise[i].level), i);
212 }
213 }
214
215
216 //-------------------------------------------------
217 // sound_stream_update - handle a stream update
218 //-------------------------------------------------
219
sound_stream_update(sound_stream & stream,stream_sample_t ** inputs,stream_sample_t ** outputs,int samples)220 void saa1099_device::sound_stream_update(sound_stream &stream, stream_sample_t **inputs, stream_sample_t **outputs, int samples)
221 {
222 int j, ch;
223 /* if the channels are disabled we're done */
224 if (!m_all_ch_enable)
225 {
226 /* init output data */
227 memset(outputs[LEFT],0,samples*sizeof(*outputs[LEFT]));
228 memset(outputs[RIGHT],0,samples*sizeof(*outputs[RIGHT]));
229 return;
230 }
231
232 for (ch = 0; ch < 2; ch++)
233 {
234 switch (m_noise_params[ch])
235 {
236 case 0: m_noise[ch].freq = m_master_clock/256.0 * 2; break;
237 case 1: m_noise[ch].freq = m_master_clock/512.0 * 2; break;
238 case 2: m_noise[ch].freq = m_master_clock/1024.0 * 2; break;
239 case 3: m_noise[ch].freq = m_channels[ch * 3].freq; break; // todo: this case will be m_master_clock/[ch*3's octave divisor, 0 is = 256*2, higher numbers are higher] * 2 if the tone generator phase reset bit (0x1c bit 1) is set.
240 }
241 }
242
243 /* fill all data needed */
244 for( j = 0; j < samples; j++ )
245 {
246 int output_l = 0, output_r = 0;
247
248 /* for each channel */
249 for (ch = 0; ch < 6; ch++)
250 {
251 if (m_channels[ch].freq == 0.0)
252 m_channels[ch].freq = (double)((2 * m_master_clock / 512) << m_channels[ch].octave) /
253 (511.0 - (double)m_channels[ch].frequency);
254
255 /* check the actual position in the square wave */
256 m_channels[ch].counter -= m_channels[ch].freq;
257 while (m_channels[ch].counter < 0)
258 {
259 /* calculate new frequency now after the half wave is updated */
260 m_channels[ch].freq = (double)((2 * m_master_clock / 512) << m_channels[ch].octave) /
261 (511.0 - (double)m_channels[ch].frequency);
262
263 m_channels[ch].counter += m_sample_rate;
264 m_channels[ch].level ^= 1;
265
266 /* eventually clock the envelope counters */
267 if (ch == 1 && m_env_clock[0] == 0)
268 envelope_w(0);
269 if (ch == 4 && m_env_clock[1] == 0)
270 envelope_w(1);
271 }
272
273 // if the noise is enabled
274 if (m_channels[ch].noise_enable)
275 {
276 // if the noise level is high (noise 0: chan 0-2, noise 1: chan 3-5)
277 if (m_noise[ch/3].level & 1)
278 {
279 // subtract to avoid overflows, also use only half amplitude
280 output_l -= m_channels[ch].amplitude[ LEFT] * m_channels[ch].envelope[ LEFT] / 16 / 2;
281 output_r -= m_channels[ch].amplitude[RIGHT] * m_channels[ch].envelope[RIGHT] / 16 / 2;
282 }
283 }
284 // if the square wave is enabled
285 if (m_channels[ch].freq_enable)
286 {
287 // if the channel level is high
288 if (m_channels[ch].level & 1)
289 {
290 output_l += m_channels[ch].amplitude[ LEFT] * m_channels[ch].envelope[ LEFT] / 16;
291 output_r += m_channels[ch].amplitude[RIGHT] * m_channels[ch].envelope[RIGHT] / 16;
292 }
293 }
294 }
295
296 for (ch = 0; ch < 2; ch++)
297 {
298 /* update the state of the noise generator
299 * polynomial is x^18 + x^11 + x (i.e. 0x20400) and is a plain XOR, initial state is probably all 1s
300 * see http://www.vogons.org/viewtopic.php?f=9&t=51695 */
301 m_noise[ch].counter -= m_noise[ch].freq;
302 while (m_noise[ch].counter < 0)
303 {
304 m_noise[ch].counter += m_sample_rate;
305 if( ((m_noise[ch].level & 0x20000) == 0) != ((m_noise[ch].level & 0x0400) == 0) )
306 m_noise[ch].level = (m_noise[ch].level << 1) | 1;
307 else
308 m_noise[ch].level <<= 1;
309 }
310 }
311 /* write sound data to the buffer */
312 outputs[LEFT][j] = output_l / 6;
313 outputs[RIGHT][j] = output_r / 6;
314 }
315 }
316
317
envelope_w(int ch)318 void saa1099_device::envelope_w(int ch)
319 {
320 if (m_env_enable[ch])
321 {
322 int step, mode, mask;
323 mode = m_env_mode[ch];
324 /* step from 0..63 and then loop in steps 32..63 */
325 step = m_env_step[ch] =
326 ((m_env_step[ch] + 1) & 0x3f) | (m_env_step[ch] & 0x20);
327
328 mask = 15;
329 if (m_env_bits[ch])
330 mask &= ~1; /* 3 bit resolution, mask LSB */
331
332 m_channels[ch*3+0].envelope[ LEFT] =
333 m_channels[ch*3+1].envelope[ LEFT] =
334 m_channels[ch*3+2].envelope[ LEFT] = envelope[mode][step] & mask;
335 if (m_env_reverse_right[ch] & 0x01)
336 {
337 m_channels[ch*3+0].envelope[RIGHT] =
338 m_channels[ch*3+1].envelope[RIGHT] =
339 m_channels[ch*3+2].envelope[RIGHT] = (15 - envelope[mode][step]) & mask;
340 }
341 else
342 {
343 m_channels[ch*3+0].envelope[RIGHT] =
344 m_channels[ch*3+1].envelope[RIGHT] =
345 m_channels[ch*3+2].envelope[RIGHT] = envelope[mode][step] & mask;
346 }
347 }
348 else
349 {
350 /* envelope mode off, set all envelope factors to 16 */
351 m_channels[ch*3+0].envelope[ LEFT] =
352 m_channels[ch*3+1].envelope[ LEFT] =
353 m_channels[ch*3+2].envelope[ LEFT] =
354 m_channels[ch*3+0].envelope[RIGHT] =
355 m_channels[ch*3+1].envelope[RIGHT] =
356 m_channels[ch*3+2].envelope[RIGHT] = 16;
357 }
358 }
359
360
WRITE8_MEMBER(saa1099_device::control_w)361 WRITE8_MEMBER( saa1099_device::control_w )
362 {
363 if ((data & 0xff) > 0x1c)
364 {
365 /* Error! */
366 logerror("%s: (SAA1099 '%s') Unknown register selected\n", machine().describe_context(), tag());
367 }
368
369 m_selected_reg = data & 0x1f;
370 if (m_selected_reg == 0x18 || m_selected_reg == 0x19)
371 {
372 /* clock the envelope channels */
373 if (m_env_clock[0])
374 envelope_w(0);
375 if (m_env_clock[1])
376 envelope_w(1);
377 }
378 }
379
380
WRITE8_MEMBER(saa1099_device::data_w)381 WRITE8_MEMBER( saa1099_device::data_w )
382 {
383 int reg = m_selected_reg;
384 int ch;
385
386 /* first update the stream to this point in time */
387 m_stream->update();
388
389 switch (reg)
390 {
391 /* channel i amplitude */
392 case 0x00: case 0x01: case 0x02: case 0x03: case 0x04: case 0x05:
393 ch = reg & 7;
394 m_channels[ch].amplitude[LEFT] = amplitude_lookup[data & 0x0f];
395 m_channels[ch].amplitude[RIGHT] = amplitude_lookup[(data >> 4) & 0x0f];
396 break;
397 /* channel i frequency */
398 case 0x08: case 0x09: case 0x0a: case 0x0b: case 0x0c: case 0x0d:
399 ch = reg & 7;
400 m_channels[ch].frequency = data & 0xff;
401 break;
402 /* channel i octave */
403 case 0x10: case 0x11: case 0x12:
404 ch = (reg - 0x10) << 1;
405 m_channels[ch + 0].octave = data & 0x07;
406 m_channels[ch + 1].octave = (data >> 4) & 0x07;
407 break;
408 /* channel i frequency enable */
409 case 0x14:
410 m_channels[0].freq_enable = data & 0x01;
411 m_channels[1].freq_enable = data & 0x02;
412 m_channels[2].freq_enable = data & 0x04;
413 m_channels[3].freq_enable = data & 0x08;
414 m_channels[4].freq_enable = data & 0x10;
415 m_channels[5].freq_enable = data & 0x20;
416 break;
417 /* channel i noise enable */
418 case 0x15:
419 m_channels[0].noise_enable = data & 0x01;
420 m_channels[1].noise_enable = data & 0x02;
421 m_channels[2].noise_enable = data & 0x04;
422 m_channels[3].noise_enable = data & 0x08;
423 m_channels[4].noise_enable = data & 0x10;
424 m_channels[5].noise_enable = data & 0x20;
425 break;
426 /* noise generators parameters */
427 case 0x16:
428 m_noise_params[0] = data & 0x03;
429 m_noise_params[1] = (data >> 4) & 0x03;
430 break;
431 /* envelope generators parameters */
432 case 0x18: case 0x19:
433 ch = reg - 0x18;
434 m_env_reverse_right[ch] = data & 0x01;
435 m_env_mode[ch] = (data >> 1) & 0x07;
436 m_env_bits[ch] = data & 0x10;
437 m_env_clock[ch] = data & 0x20;
438 m_env_enable[ch] = data & 0x80;
439 /* reset the envelope */
440 m_env_step[ch] = 0;
441 break;
442 /* channels enable & reset generators */
443 case 0x1c:
444 m_all_ch_enable = data & 0x01;
445 m_sync_state = data & 0x02;
446 if (data & 0x02)
447 {
448 int i;
449
450 /* Synch & Reset generators */
451 logerror("%s: (SAA1099 '%s') -reg 0x1c- Chip reset\n", machine().describe_context(), tag());
452 for (i = 0; i < 6; i++)
453 {
454 m_channels[i].level = 0;
455 m_channels[i].counter = 0.0;
456 }
457 }
458 break;
459 default: /* Error! */
460 if (data != 0)
461 logerror("%s: (SAA1099 '%s') Unknown operation (reg:%02x, data:%02x)\n", machine().describe_context(), tag(), reg, data);
462 }
463 }
464
WRITE8_MEMBER(saa1099_device::write)465 WRITE8_MEMBER(saa1099_device::write)
466 {
467 if (offset & 1)
468 control_w(space, 0, data);
469 else
470 data_w(space, 0, data);
471 }
472