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