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)71int 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)97int 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)122int 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)155int 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)183int 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)212int 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)224int 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)242int 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)262int 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)309int 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)319int 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)338int 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)357int 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)388int 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)396int 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)404int 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)422int 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)442int 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)480int 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)493int 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)511int 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)531int 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)556int 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)581int 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)606int 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)631int 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)656int 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)681int 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