1 /************************************************************************/
2 /*                                                                      */
3 /*  MAME - Discrete sound system emulation library                      */
4 /*                                                                      */
5 /*  Written by Keith Wilkins (mame@esplexo.co.uk)                       */
6 /*                                                                      */
7 /*  (c) K.Wilkins 2000                                                  */
8 /*                                                                      */
9 /************************************************************************/
10 /*                                                                      */
11 /* DST_ADDDER            - Multichannel adder                           */
12 /* DST_GAIN              - Gain Factor                                  */
13 /* DST_SWITCH            - Switch implementation                        */
14 /* DST_RAMP              - Ramp up/down                                 */
15 /* DST_ONESHOT           - One shot pulse generator                     */
16 /* DST_DIVIDER           - Division function                            */
17 /* DST_LADDER            - Resistor ladder implementation               */
18 /* DST_SAMPHOLD          - Sample & Hold Implementation                 */
19 /* DST_LOGIC_INV         - Logic level invertor                         */
20 /* DST_LOGIC_AND         - Logic AND gate 4 input                       */
21 /* DST_LOGIC_NAND        - Logic NAND gate 4 input                      */
22 /* DST_LOGIC_OR          - Logic OR gate 4 input                        */
23 /* DST_LOGIC_NOR         - Logic NOR gate 4 input                       */
24 /* DST_LOGIC_XOR         - Logic XOR gate 2 input                       */
25 /* DST_LOGIC_NXOR        - Logic NXOR gate 2 input                      */
26 /*                                                                      */
27 /************************************************************************/
28 
29 
30 struct dss_ramp_context
31 {
32         float step;
33         int dir;	/* 1 if End is higher then Start */
34 	int last_en;	/* Keep track of the last enable value */
35 };
36 
37 struct dst_oneshot_context
38 {
39 	float countdown;
40 	float stepsize;
41 	int state;
42 };
43 
44 struct dst_ladder_context
45 {
46         int state;
47         float t;           // time
48         float step;
49 		float exponent0;
50 		float exponent1;
51 };
52 
53 struct dst_samphold_context
54 {
55 		float lastinput;
56 		int clocktype;
57 };
58 
59 /************************************************************************/
60 /*                                                                      */
61 /* DST_ADDER - This is a 4 channel input adder with enable function     */
62 /*                                                                      */
63 /* input0    - Enable input value                                       */
64 /* input1    - Channel0 input value                                     */
65 /* input2    - Channel1 input value                                     */
66 /* input3    - Channel2 input value                                     */
67 /* input4    - Channel3 input value                                     */
68 /* input5    - NOT USED                                                 */
69 /*                                                                      */
70 /************************************************************************/
dst_adder_step(struct node_description * node)71 int dst_adder_step(struct node_description *node)
72 {
73 	if(node->input0)
74 	{
75 		node->output=node->input1 + node->input2 + node->input3 + node->input4;
76 	}
77 	else
78 	{
79 		node->output=0;
80 	}
81 	return 0;
82 }
83 
84 
85 /************************************************************************/
86 /*                                                                      */
87 /* DST_GAIN - This is a programmable gain module with enable function   */
88 /*                                                                      */
89 /* input0    - Enable input value                                       */
90 /* input1    - Channel0 input value                                     */
91 /* input2    - Gain value                                               */
92 /* input3    - NOT USED                                                 */
93 /* input4    - NOT USED                                                 */
94 /* input5    - NOT USED                                                 */
95 /*                                                                      */
96 /************************************************************************/
dst_gain_step(struct node_description * node)97 int dst_gain_step(struct node_description *node)
98 {
99 	if(node->input0)
100 	{
101 		node->output=node->input1 * node->input2;
102 	}
103 	else
104 	{
105 		node->output=0;
106 	}
107 	return 0;
108 }
109 
110 /************************************************************************/
111 /*                                                                      */
112 /* DST_DIVIDE  - Programmable divider with enable                       */
113 /*                                                                      */
114 /* input0    - Enable input value                                       */
115 /* input1    - Channel0 input value                                     */
116 /* input2    - Divisor                                                  */
117 /* input3    - NOT USED                                                 */
118 /* input4    - NOT USED                                                 */
119 /* input5    - NOT USED                                                 */
120 /*                                                                      */
121 /************************************************************************/
dst_divide_step(struct node_description * node)122 int dst_divide_step(struct node_description *node)
123 {
124 	if(node->input0)
125 	{
126 		if(node->input2==0)
127 		{
128 			node->output=2^31;	/* Max out but dont break */
129 
130 		}
131 		else
132 		{
133 			node->output=node->input1 / node->input2;
134 		}
135 	}
136 	else
137 	{
138 		node->output=0;
139 	}
140 	return 0;
141 }
142 
143 /************************************************************************/
144 /*                                                                      */
145 /* DSS_SWITCH - Programmable 2 pole switchmodule with enable function   */
146 /*                                                                      */
147 /* input0    - Enable input value                                       */
148 /* input1    - switch position                                          */
149 /* input2    - input0                                                   */
150 /* input3    - input1                                                   */
151 /* input4    - NOT USED                                                 */
152 /* input5    - NOT USED                                                 */
153 /*                                                                      */
154 /************************************************************************/
dst_switch_step(struct node_description * node)155 int dst_switch_step(struct node_description *node)
156 {
157 	if(node->input0)
158 	{
159 		/* Input 1 switches between input0/input2 */
160 		node->output=(node->input1)?node->input3:node->input2;
161 	}
162 	else
163 	{
164 		node->output=0;
165 	}
166 	return 0;
167 }
168 
169 
170 /************************************************************************/
171 /*                                                                      */
172 /* DST_RAMP - Ramp up/down model usage                                  */
173 /*                                                                      */
174 /* input0    - Enable ramp                                              */
175 /* input1    - Ramp Reverse/Forward switch                              */
176 /* input2    - Gradient, change/sec                                     */
177 /* input3    - Start value                                              */
178 /* input4    - End value                                                */
179 /* input5    - Clamp value when disabled                                */
180 /*                                                                      */
181 /************************************************************************/
182 
dst_ramp_step(struct node_description * node)183 int dst_ramp_step(struct node_description *node)
184 {
185 	struct dss_ramp_context *context;
186 	context=(struct dss_ramp_context*)node->context;
187 
188 	if(node->input0)
189 	{
190 		if (!context->last_en)
191 		{
192 			context->last_en = 1;
193 			node->output = node->input3;
194 		}
195 		if(context->dir ? node->input1 : !node->input1) node->output+=context->step;
196 		else node->output-=context->step;
197 		/* Clamp to min/max */
198 		if(context->dir ? (node->output < node->input3)
199 				: (node->output > node->input3)) node->output=node->input3;
200 		if(context->dir ? (node->output > node->input4)
201 				: (node->output < node->input4)) node->output=node->input4;
202 	}
203 	else
204 	{
205 		context->last_en = 0;
206 		// Disabled so clamp to output
207 		node->output=node->input5;
208 	}
209 	return 0;
210 }
211 
dst_ramp_reset(struct node_description * node)212 int dst_ramp_reset(struct node_description *node)
213 {
214 	struct dss_ramp_context *context;
215 	context=(struct dss_ramp_context*)node->context;
216 
217 	node->output=node->input5;
218 	context->step = node->input2 / Machine->sample_rate;
219 	context->dir = ((node->input4 - node->input3) == fabs(node->input4 - node->input3));
220 	context->last_en = 0;
221 	return 0;
222 }
223 
dst_ramp_init(struct node_description * node)224 int dst_ramp_init(struct node_description *node)
225 {
226 	/* Allocate memory for the context array and the node execution order array */
227 	if((node->context=(struct dss_ramp_context*)malloc(sizeof(struct dss_ramp_context)))==NULL)
228 	{
229 		return 1;
230 	}
231 	else
232 	{
233 		/* Initialise memory */
234 		memset(node->context,0,sizeof(struct dss_ramp_context));
235 	}
236 
237 	/* Initialise the object */
238 	dst_ramp_reset(node);
239 	return 0;
240 }
241 
dst_ramp_kill(struct node_description * node)242 int dst_ramp_kill(struct node_description *node)
243 {
244 	free(node->context);
245 	node->context=NULL;
246 	return 0;
247 }
248 
249 
250 /************************************************************************/
251 /*                                                                      */
252 /* dst_oneshot - Usage of node_description values for one shot pulse    */
253 /*                                                                      */
254 /* input0    - Enable input value                                       */
255 /* input1    - Trigger value                                            */
256 /* input2    - Reset value                                              */
257 /* input3    - Amplitude value                                          */
258 /* input4    - Width of oneshot pulse                                   */
259 /* input5    - NOT USED                                                 */
260 /*                                                                      */
261 /************************************************************************/
dst_oneshot_step(struct node_description * node)262 int dst_oneshot_step(struct node_description *node)
263 {
264 	struct dst_oneshot_context *context;
265 	context=(struct dst_oneshot_context*)node->context;
266 
267 	/* Check state */
268 	switch(context->state)
269 	{
270 		case 0:		/* Waiting for trigger */
271 			if(node->input1)
272 			{
273 				context->state=1;
274 				context->countdown=node->input4;
275 				node->output=node->input3;
276 			}
277 		 	node->output=0;
278 			break;
279 
280 		case 1:		/* Triggered */
281 			node->output=node->input3;
282 			if(node->input1 && node->input2)
283 			{
284 				// Dont start the countdown if we're still triggering
285 				// and we've got a reset signal as well
286 			}
287 			else
288 			{
289 				context->countdown-=context->stepsize;
290 				if(context->countdown<0.0)
291 				{
292 					context->countdown=0;
293 					node->output=0;
294 					context->state=2;
295 				}
296 			}
297 			break;
298 
299 		case 2:		/* Waiting for reset */
300 		default:
301 			if(node->input2) context->state=0;
302 		 	node->output=0;
303 			break;
304 	}
305 	return 0;
306 }
307 
308 
dst_oneshot_reset(struct node_description * node)309 int dst_oneshot_reset(struct node_description *node)
310 {
311 	struct dst_oneshot_context *context=(struct dst_oneshot_context*)node->context;
312 	context->countdown=0;
313 	context->stepsize=1.0/Machine->sample_rate;
314 	context->state=0;
315  	node->output=0;
316  	return 0;
317 }
318 
dst_oneshot_init(struct node_description * node)319 int dst_oneshot_init(struct node_description *node)
320 {
321 	/* Allocate memory for the context array and the node execution order array */
322 	if((node->context=(struct dst_oneshot_context*)malloc(sizeof(struct dst_oneshot_context)))==NULL)
323 	{
324 		return 1;
325 	}
326 	else
327 	{
328 		/* Initialise memory */
329 		memset(node->context,0,sizeof(struct dst_oneshot_context));
330 	}
331 
332 	/* Initialise the object */
333 	dst_oneshot_reset(node);
334 
335 	return 0;
336 }
337 
dst_oneshot_kill(struct node_description * node)338 int dst_oneshot_kill(struct node_description *node)
339 {
340 	free(node->context);
341 	node->context=NULL;
342 	return 0;
343 }
344 
345 
346 /************************************************************************/
347 /*                                                                      */
348 /* DST_CLAMP - Simple signal clamping circuit                           */
349 /*                                                                      */
350 /* input0    - Enable ramp                                              */
351 /* input1    - Input value                                              */
352 /* input2    - Minimum value                                            */
353 /* input3    - Maximum value                                            */
354 /* input4    - Clamp when disabled                                      */
355 /*                                                                      */
356 /************************************************************************/
dst_clamp_step(struct node_description * node)357 int dst_clamp_step(struct node_description *node)
358 {
359 	struct dss_ramp_context *context;
360 	context=(struct dss_ramp_context*)node->context;
361 
362 	if(node->input0)
363 	{
364 		if(node->input1 < node->input2) node->output=node->input2;
365 		else if(node->input1 > node->input3) node->output=node->input3;
366 		else node->output=node->input1;
367 	}
368 	else
369 	{
370 		node->output=node->input4;
371 	}
372 	return 0;
373 }
374 
375 
376 /************************************************************************/
377 /*                                                                      */
378 /* DST_LADDER - Resistor ladder emulation complete with capacitor       */
379 /*                                                                      */
380 /* input0    - Enable                                                   */
381 /* input1    - input0 value                                             */
382 /* input2    - NOT USED                                                 */
383 /* input3    - NOT USED                                                 */
384 /* input4    - NOT USED                                                 */
385 /* input5    - NOT USED                                                 */
386 /*                                                                      */
387 /************************************************************************/
dst_ladder_step(struct node_description * node)388 int dst_ladder_step(struct node_description *node)
389 {
390 	struct dst_ladder_context *context;
391 	context=(struct dst_ladder_context*)node->context;
392 	node->output=0;
393 	return 0;
394 }
395 
dst_ladder_reset(struct node_description * node)396 int dst_ladder_reset(struct node_description *node)
397 {
398 	struct dst_ladder_context *context;
399 	context=(struct dst_ladder_context*)node->context;
400 	node->output=0;
401 	return 0;
402 }
403 
dst_ladder_init(struct node_description * node)404 int dst_ladder_init(struct node_description *node)
405 {
406 	/* Allocate memory for the context array and the node execution order array */
407 	if((node->context=(struct dst_ladder_context*)malloc(sizeof(struct dst_ladder_context)))==NULL)
408 	{
409 		return 1;
410 	}
411 	else
412 	{
413 		/* Initialise memory */
414 		memset(node->context,0,sizeof(struct dst_ladder_context));
415 	}
416 
417 	/* Initialise the object */
418 	dst_ladder_reset(node);
419 	return 0;
420 }
421 
dst_ladder_kill(struct node_description * node)422 int dst_ladder_kill(struct node_description *node)
423 {
424 	free(node->context);
425 	node->context=NULL;
426 	return 0;
427 }
428 
429 
430 /************************************************************************/
431 /*                                                                      */
432 /* DST_SAMPHOLD - Sample & Hold Implementation                          */
433 /*                                                                      */
434 /* input0    - Enable                                                   */
435 /* input1    - input0 value                                             */
436 /* input2    - clock node                                               */
437 /* input3    - clock type                                               */
438 /* input4    - NOT USED                                                 */
439 /* input5    - NOT USED                                                 */
440 /*                                                                      */
441 /************************************************************************/
dst_samphold_step(struct node_description * node)442 int dst_samphold_step(struct node_description *node)
443 {
444 	struct dst_samphold_context *context;
445 	context=(struct dst_samphold_context*)node->context;
446 
447 	if(node->input0)
448 	{
449 		switch(context->clocktype)
450 		{
451 			case DISC_SAMPHOLD_REDGE:
452 				/* Clock the whole time the input is rising */
453 				if(node->input2 > context->lastinput) node->output=node->input1;
454 				break;
455 			case DISC_SAMPHOLD_FEDGE:
456 				/* Clock the whole time the input is falling */
457 				if(node->input2 < context->lastinput) node->output=node->input1;
458 				break;
459 			case DISC_SAMPHOLD_HLATCH:
460 				/* Output follows input if clock != 0 */
461 				if(node->input2) node->output=node->input1;
462 				break;
463 			case DISC_SAMPHOLD_LLATCH:
464 				/* Output follows input if clock == 0 */
465 				if(node->input2==0) node->output=node->input1;
466 				break;
467 			default:
468 				break;
469 		}
470 	}
471 	else
472 	{
473 		node->output=0;
474 	}
475 	/* Save the last value */
476 	context->lastinput=node->input2;
477 	return 0;
478 }
479 
dst_samphold_reset(struct node_description * node)480 int dst_samphold_reset(struct node_description *node)
481 {
482 	struct dst_samphold_context *context;
483 	context=(struct dst_samphold_context*)node->context;
484 
485 	node->output=0;
486 	context->lastinput=-1;
487 	/* Only stored in here to speed up and save casting in the step function */
488 	context->clocktype=(int)node->input3;
489 
490 	return 0;
491 }
492 
dst_samphold_init(struct node_description * node)493 int dst_samphold_init(struct node_description *node)
494 {
495 	/* Allocate memory for the context array and the node execution order array */
496 	if((node->context=(struct dst_samphold_context*)malloc(sizeof(struct dst_samphold_context)))==NULL)
497 	{
498 		return 1;
499 	}
500 	else
501 	{
502 		/* Initialise memory */
503 		memset(node->context,0,sizeof(struct dst_samphold_context));
504 	}
505 
506 	/* Initialise the object */
507 	dst_samphold_reset(node);
508 	return 0;
509 }
510 
dst_samphold_kill(struct node_description * node)511 int dst_samphold_kill(struct node_description *node)
512 {
513 	free(node->context);
514 	node->context=NULL;
515 	return 0;
516 }
517 
518 
519 /************************************************************************/
520 /*                                                                      */
521 /* DST_LOGIC_INV - Logic invertor gate implementation                   */
522 /*                                                                      */
523 /* input0    - Enable                                                   */
524 /* input1    - input0 value                                             */
525 /* input2    - NOT USED                                                 */
526 /* input3    - NOT USED                                                 */
527 /* input4    - NOT USED                                                 */
528 /* input5    - NOT USED                                                 */
529 /*                                                                      */
530 /************************************************************************/
dst_logic_inv_step(struct node_description * node)531 int dst_logic_inv_step(struct node_description *node)
532 {
533 	if(node->input0)
534 	{
535 		node->output=(node->input1)?0.0:1.0;
536 	}
537 	else
538 	{
539 		node->output=0.0;
540 	}
541 	return 0;
542 }
543 
544 /************************************************************************/
545 /*                                                                      */
546 /* DST_LOGIC_AND - Logic AND gate implementation                        */
547 /*                                                                      */
548 /* input0    - Enable                                                   */
549 /* input1    - input0 value                                             */
550 /* input2    - input1 value                                             */
551 /* input3    - input2 value                                             */
552 /* input4    - input3 value                                             */
553 /* input5    - NOT USED                                                 */
554 /*                                                                      */
555 /************************************************************************/
dst_logic_and_step(struct node_description * node)556 int dst_logic_and_step(struct node_description *node)
557 {
558 	if(node->input0)
559 	{
560 		node->output=(node->input1 && node->input2 && node->input3 && node->input4)?1.0:0.0;
561 	}
562 	else
563 	{
564 		node->output=0.0;
565 	}
566 	return 0;
567 }
568 
569 /************************************************************************/
570 /*                                                                      */
571 /* DST_LOGIC_NAND - Logic NAND gate implementation                      */
572 /*                                                                      */
573 /* input0    - Enable                                                   */
574 /* input1    - input0 value                                             */
575 /* input2    - input1 value                                             */
576 /* input3    - input2 value                                             */
577 /* input4    - input3 value                                             */
578 /* input5    - NOT USED                                                 */
579 /*                                                                      */
580 /************************************************************************/
dst_logic_nand_step(struct node_description * node)581 int dst_logic_nand_step(struct node_description *node)
582 {
583 	if(node->input0)
584 	{
585 		node->output=(node->input1 && node->input2 && node->input3 && node->input4)?0.0:1.0;
586 	}
587 	else
588 	{
589 		node->output=0.0;
590 	}
591 	return 0;
592 }
593 
594 /************************************************************************/
595 /*                                                                      */
596 /* DST_LOGIC_OR  - Logic OR  gate implementation                        */
597 /*                                                                      */
598 /* input0    - Enable                                                   */
599 /* input1    - input0 value                                             */
600 /* input2    - input1 value                                             */
601 /* input3    - input2 value                                             */
602 /* input4    - input3 value                                             */
603 /* input5    - NOT USED                                                 */
604 /*                                                                      */
605 /************************************************************************/
dst_logic_or_step(struct node_description * node)606 int dst_logic_or_step(struct node_description *node)
607 {
608 	if(node->input0)
609 	{
610 		node->output=(node->input1 || node->input2 || node->input3 || node->input4)?1.0:0.0;
611 	}
612 	else
613 	{
614 		node->output=0.0;
615 	}
616 	return 0;
617 }
618 
619 /************************************************************************/
620 /*                                                                      */
621 /* DST_LOGIC_NOR - Logic NOR gate implementation                        */
622 /*                                                                      */
623 /* input0    - Enable                                                   */
624 /* input1    - input0 value                                             */
625 /* input2    - input1 value                                             */
626 /* input3    - input2 value                                             */
627 /* input4    - input3 value                                             */
628 /* input5    - NOT USED                                                 */
629 /*                                                                      */
630 /************************************************************************/
dst_logic_nor_step(struct node_description * node)631 int dst_logic_nor_step(struct node_description *node)
632 {
633 	if(node->input0)
634 	{
635 		node->output=(node->input1 || node->input2 || node->input3 || node->input4)?0.0:1.0;
636 	}
637 	else
638 	{
639 		node->output=0.0;
640 	}
641 	return 0;
642 }
643 
644 /************************************************************************/
645 /*                                                                      */
646 /* DST_LOGIC_XOR - Logic XOR gate implementation                        */
647 /*                                                                      */
648 /* input0    - Enable                                                   */
649 /* input1    - input0 value                                             */
650 /* input2    - input1 value                                             */
651 /* input3    - NOT USED                                                 */
652 /* input4    - NOT USED                                                 */
653 /* input5    - NOT USED                                                 */
654 /*                                                                      */
655 /************************************************************************/
dst_logic_xor_step(struct node_description * node)656 int dst_logic_xor_step(struct node_description *node)
657 {
658 	if(node->input0)
659 	{
660 		node->output=((node->input1 && !node->input2) || (!node->input1 && node->input2))?1.0:0.0;
661 	}
662 	else
663 	{
664 		node->output=0.0;
665 	}
666 	return 0;
667 }
668 
669 /************************************************************************/
670 /*                                                                      */
671 /* DST_LOGIC_NXOR - Logic NXOR gate implementation                      */
672 /*                                                                      */
673 /* input0    - Enable                                                   */
674 /* input1    - input0 value                                             */
675 /* input2    - input1 value                                             */
676 /* input3    - NOT USED                                                 */
677 /* input4    - NOT USED                                                 */
678 /* input5    - NOT USED                                                 */
679 /*                                                                      */
680 /************************************************************************/
dst_logic_nxor_step(struct node_description * node)681 int dst_logic_nxor_step(struct node_description *node)
682 {
683 	if(node->input0)
684 	{
685 		node->output=((node->input1 && !node->input2) || (!node->input1 && node->input2))?0.0:1.0;
686 	}
687 	else
688 	{
689 		node->output=0.0;
690 	}
691 	return 0;
692 }
693