Previous 199869 Revisions Next

r28732 Wednesday 19th March, 2014 at 17:40:26 UTC by Oliver Stöneberg
renamed disc_*.c to disc_*.inc
[src/emu/sound]disc_cls.h disc_dev.c disc_dev.inc* disc_flt.c disc_flt.inc* disc_inp.c disc_inp.inc* disc_mth.c disc_mth.inc* disc_sys.c disc_sys.inc* disc_wav.c disc_wav.inc* discrete.c discrete.h sound.mak

trunk/src/emu/sound/disc_dev.c
r28731r28732
1/************************************************************************
2 *
3 *  MAME - Discrete sound system emulation library
4 *
5 *  Written by Keith Wilkins (mame@dysfunction.demon.co.uk)
6 *
7 *  (c) K.Wilkins 2000
8 *  (c) D.Renaud 2003-2004
9 *
10 ************************************************************************
11 *
12 * DSD_555_ASTBL         - NE555 Simulation - Astable mode
13 * DSD_555_MSTBL         - NE555 Simulation - Monostable mode
14 * DSD_555_CC            - NE555 Constant Current VCO
15 * DSD_555_VCO1          - Op-Amp linear ramp based 555 VCO
16 * DSD_566               - NE566 Simulation
17 * DSD_LS624             - 74LS624/629 Simulation
18 *
19 ************************************************************************
20 *
21 * You will notice that the code for a lot of these routines are similar.
22 * I tried to make a common charging routine, but there are too many
23 * minor differences that affect each module.
24 *
25 ************************************************************************/
26
27#define DEFAULT_555_BLEED_R RES_M(10)
28
29/************************************************************************
30 *
31 * DSD_555_ASTBL -  - 555 Astable simulation
32 *
33 * input[0]    - Reset value
34 * input[1]    - R1 value
35 * input[2]    - R2 value
36 * input[3]    - C value
37 * input[4]    - Control Voltage value
38 *
39 * also passed discrete_555_desc structure
40 *
41 * Jan 2004, D Renaud.
42 ************************************************************************/
43#define DSD_555_ASTBL__RESET    (! DISCRETE_INPUT(0))
44#define DSD_555_ASTBL__R1       DISCRETE_INPUT(1)
45#define DSD_555_ASTBL__R2       DISCRETE_INPUT(2)
46#define DSD_555_ASTBL__C        DISCRETE_INPUT(3)
47#define DSD_555_ASTBL__CTRLV    DISCRETE_INPUT(4)
48
49/* bit mask of the above RC inputs */
50#define DSD_555_ASTBL_RC_MASK   0x0e
51
52/* charge/discharge constants */
53#define DSD_555_ASTBL_T_RC_BLEED        (DEFAULT_555_BLEED_R * DSD_555_ASTBL__C)
54/* Use quick charge if specified. */
55#define DSD_555_ASTBL_T_RC_CHARGE       ((DSD_555_ASTBL__R1 + ((info->options & DISC_555_ASTABLE_HAS_FAST_CHARGE_DIODE) ? 0 : DSD_555_ASTBL__R2)) * DSD_555_ASTBL__C)
56#define DSD_555_ASTBL_T_RC_DISCHARGE    (DSD_555_ASTBL__R2 * DSD_555_ASTBL__C)
57
58DISCRETE_STEP(dsd_555_astbl)
59{
60   DISCRETE_DECLARE_INFO(discrete_555_desc)
61
62   int     count_f = 0;
63   int     count_r = 0;
64   double  dt;                             /* change in time */
65   double  x_time  = 0;                    /* time since change happened */
66   double  v_cap   = m_cap_voltage;    /* Current voltage on capacitor, before dt */
67   double  v_cap_next = 0;                 /* Voltage on capacitor, after dt */
68   double  v_charge, exponent = 0;
69   UINT8   flip_flop = m_flip_flop;
70   UINT8   update_exponent = 0;
71   double  v_out = 0.0;
72
73   /* put commonly used stuff in local variables for speed */
74   double  threshold = m_threshold;
75   double  trigger   = m_trigger;
76
77   if(DSD_555_ASTBL__RESET)
78   {
79      /* We are in RESET */
80      set_output(0, 0);
81      m_flip_flop   = 1;
82      m_cap_voltage = 0;
83      return;
84   }
85
86   /* Check: if the Control Voltage node is connected. */
87   if (m_use_ctrlv)
88   {
89      /* If CV is less then .25V, the circuit will oscillate way out of range.
90       * So we will just ignore it when it happens. */
91      if (DSD_555_ASTBL__CTRLV < .25) return;
92      /* If it is a node then calculate thresholds based on Control Voltage */
93      threshold = DSD_555_ASTBL__CTRLV;
94      trigger   = DSD_555_ASTBL__CTRLV / 2.0;
95      /* Since the thresholds may have changed we need to update the FF */
96      if (v_cap >= threshold)
97      {
98         flip_flop = 0;
99         count_f++;
100      }
101      else
102      if (v_cap <= trigger)
103      {
104         flip_flop = 1;
105         count_r++;
106      }
107   }
108
109   /* get the v_charge and update each step if it is a node */
110   if (m_v_charge_node != NULL)
111   {
112      v_charge = *m_v_charge_node;
113      if (info->options & DISC_555_ASTABLE_HAS_FAST_CHARGE_DIODE) v_charge -= 0.5;
114   }
115   else
116      v_charge = m_v_charge;
117
118
119   /* Calculate future capacitor voltage.
120    * ref@ http://www.physics.rutgers.edu/ugrad/205/capacitance.html
121    * The formulas from the ref pages have been modified to reflect that we are stepping the change.
122    * dt = time of sample (1/sample frequency)
123    * VC = Voltage across capacitor
124    * VC' = Future voltage across capacitor
125    * Vc = Voltage change
126    * Vr = is the voltage across the resistor.  For charging it is Vcc - VC.  Discharging it is VC - 0.
127    * R = R1+R2 (for charging)  R = R2 for discharging.
128    * Vc = Vr*(1-exp(-dt/(R*C)))
129    * VC' = VC + Vc (for charging) VC' = VC - Vc for discharging.
130    *
131    * We will also need to calculate the amount of time we overshoot the thresholds
132    * dt = amount of time we overshot
133    * Vc = voltage change overshoot
134    * dt = R*C(log(1/(1-(Vc/Vr))))
135    */
136
137   dt = this->sample_time();
138
139   /* Sometimes a switching network is used to setup the capacitance.
140    * These may select no capacitor, causing oscillation to stop.
141    */
142   if (DSD_555_ASTBL__C == 0)
143   {
144      flip_flop = 1;
145      /* The voltage goes high because the cap circuit is open. */
146      v_cap_next = v_charge;
147      v_cap      = v_charge;
148      m_cap_voltage = 0;
149   }
150   else
151   {
152      /* Update charge contstants and exponents if nodes changed */
153      if (m_has_rc_nodes && (DSD_555_ASTBL__R1 != m_last_r1 || DSD_555_ASTBL__C != m_last_c || DSD_555_ASTBL__R2 != m_last_r2))
154      {
155         m_t_rc_bleed  = DSD_555_ASTBL_T_RC_BLEED;
156         m_t_rc_charge = DSD_555_ASTBL_T_RC_CHARGE;
157         m_t_rc_discharge = DSD_555_ASTBL_T_RC_DISCHARGE;
158         m_exp_bleed  = RC_CHARGE_EXP(m_t_rc_bleed);
159         m_exp_charge = RC_CHARGE_EXP(m_t_rc_charge);
160         m_exp_discharge = RC_CHARGE_EXP(m_t_rc_discharge);
161         m_last_r1 = DSD_555_ASTBL__R1;
162         m_last_r2 = DSD_555_ASTBL__R2;
163         m_last_c  = DSD_555_ASTBL__C;
164      }
165      /* Keep looping until all toggling in time sample is used up. */
166      do
167      {
168         if (flip_flop)
169         {
170            if (DSD_555_ASTBL__R1 == 0)
171            {
172               /* Oscillation disabled because there is no longer any charge resistor. */
173               /* Bleed the cap due to circuit losses. */
174               if (update_exponent)
175                  exponent = RC_CHARGE_EXP_DT(m_t_rc_bleed, dt);
176               else
177                  exponent = m_exp_bleed;
178               v_cap_next = v_cap - (v_cap * exponent);
179               dt = 0;
180            }
181            else
182            {
183               /* Charging */
184               if (update_exponent)
185                  exponent = RC_CHARGE_EXP_DT(m_t_rc_charge, dt);
186               else
187                  exponent = m_exp_charge;
188               v_cap_next = v_cap + ((v_charge - v_cap) * exponent);
189               dt = 0;
190
191               /* has it charged past upper limit? */
192               if (v_cap_next >= threshold)
193               {
194                  /* calculate the overshoot time */
195                  dt     = m_t_rc_charge  * log(1.0 / (1.0 - ((v_cap_next - threshold) / (v_charge - v_cap))));
196                  x_time = dt;
197                  v_cap_next  = threshold;
198                  flip_flop = 0;
199                  count_f++;
200                  update_exponent = 1;
201               }
202            }
203         }
204         else
205         {
206            /* Discharging */
207            if(DSD_555_ASTBL__R2 != 0)
208            {
209               if (update_exponent)
210                  exponent = RC_CHARGE_EXP_DT(m_t_rc_discharge, dt);
211               else
212                  exponent = m_exp_discharge;
213               v_cap_next = v_cap - (v_cap * exponent);
214               dt = 0;
215            }
216            else
217            {
218               /* no discharge resistor so we immediately discharge */
219               v_cap_next = trigger;
220            }
221
222            /* has it discharged past lower limit? */
223            if (v_cap_next <= trigger)
224            {
225               /* calculate the overshoot time */
226               if (v_cap_next < trigger)
227                  dt = m_t_rc_discharge  * log(1.0 / (1.0 - ((trigger - v_cap_next) / v_cap)));
228               x_time = dt;
229               v_cap_next  = trigger;
230               flip_flop = 1;
231               count_r++;
232               update_exponent = 1;
233            }
234         }
235         v_cap = v_cap_next;
236      } while(dt);
237
238      m_cap_voltage = v_cap;
239   }
240
241   /* Convert last switch time to a ratio */
242   x_time = x_time / this->sample_time();
243
244   switch (m_output_type)
245   {
246      case DISC_555_OUT_SQW:
247         if (count_f + count_r >= 2)
248            /* force at least 1 toggle */
249            v_out =  m_flip_flop ? 0 : m_v_out_high;
250         else
251            v_out =  flip_flop * m_v_out_high;
252         v_out += m_ac_shift;
253         break;
254      case DISC_555_OUT_CAP:
255         v_out =  v_cap;
256         /* Fake it to AC if needed */
257         if (m_output_is_ac)
258            v_out -= threshold * 3.0 /4.0;
259         break;
260      case DISC_555_OUT_ENERGY:
261         if (x_time == 0) x_time = 1.0;
262         v_out = m_v_out_high * (flip_flop ? x_time : (1.0 - x_time));
263         v_out += m_ac_shift;
264         break;
265      case DISC_555_OUT_LOGIC_X:
266         v_out =  flip_flop + x_time;
267         break;
268      case DISC_555_OUT_COUNT_F_X:
269         v_out = count_f ? count_f + x_time : count_f;
270         break;
271      case DISC_555_OUT_COUNT_R_X:
272         v_out =  count_r ? count_r + x_time : count_r;
273         break;
274      case DISC_555_OUT_COUNT_F:
275         v_out =  count_f;
276         break;
277      case DISC_555_OUT_COUNT_R:
278         v_out =  count_r;
279         break;
280   }
281   set_output(0, v_out);
282   m_flip_flop = flip_flop;
283}
284
285DISCRETE_RESET(dsd_555_astbl)
286{
287   DISCRETE_DECLARE_INFO(discrete_555_desc)
288
289   m_use_ctrlv   = (this->input_is_node() >> 4) & 1;
290   m_output_type = info->options & DISC_555_OUT_MASK;
291
292   /* Use the defaults or supplied values. */
293   m_v_out_high = (info->v_out_high == DEFAULT_555_HIGH) ? info->v_pos - 1.2 : info->v_out_high;
294
295   /* setup v_charge or node */
296   m_v_charge_node = m_device->node_output_ptr(info->v_charge);
297   if (m_v_charge_node == NULL)
298   {
299      m_v_charge   = (info->v_charge == DEFAULT_555_CHARGE) ? info->v_pos : info->v_charge;
300
301      if (info->options & DISC_555_ASTABLE_HAS_FAST_CHARGE_DIODE) m_v_charge -= 0.5;
302   }
303
304   if ((DSD_555_ASTBL__CTRLV != -1) && !m_use_ctrlv)
305   {
306      /* Setup based on supplied Control Voltage static value */
307      m_threshold = DSD_555_ASTBL__CTRLV;
308      m_trigger   = DSD_555_ASTBL__CTRLV / 2.0;
309   }
310   else
311   {
312      /* Setup based on v_pos power source */
313      m_threshold = info->v_pos * 2.0 / 3.0;
314      m_trigger   = info->v_pos / 3.0;
315   }
316
317   /* optimization if none of the values are nodes */
318   m_has_rc_nodes = 0;
319   if (this->input_is_node() & DSD_555_ASTBL_RC_MASK)
320      m_has_rc_nodes = 1;
321   else
322   {
323      m_t_rc_bleed  = DSD_555_ASTBL_T_RC_BLEED;
324      m_exp_bleed   = RC_CHARGE_EXP(m_t_rc_bleed);
325      m_t_rc_charge = DSD_555_ASTBL_T_RC_CHARGE;
326      m_exp_charge  = RC_CHARGE_EXP(m_t_rc_charge);
327      m_t_rc_discharge = DSD_555_ASTBL_T_RC_DISCHARGE;
328      m_exp_discharge  = RC_CHARGE_EXP(m_t_rc_discharge);
329   }
330
331   m_output_is_ac = info->options & DISC_555_OUT_AC;
332   /* Calculate DC shift needed to make squarewave waveform AC */
333   m_ac_shift = m_output_is_ac ? -m_v_out_high / 2.0 : 0;
334
335   m_flip_flop = 1;
336   m_cap_voltage = 0;
337
338   /* Step to set the output */
339   this->step();
340}
341
342
343/************************************************************************
344 *
345 * DSD_555_MSTBL - 555 Monostable simulation
346 *
347 * input[0]    - Reset value
348 * input[1]    - Trigger input
349 * input[2]    - R2 value
350 * input[3]    - C value
351 *
352 * also passed discrete_555_desc structure
353 *
354 * Oct 2004, D Renaud.
355 ************************************************************************/
356#define DSD_555_MSTBL__RESET    (! DISCRETE_INPUT(0))
357#define DSD_555_MSTBL__TRIGGER  DISCRETE_INPUT(1)
358#define DSD_555_MSTBL__R        DISCRETE_INPUT(2)
359#define DSD_555_MSTBL__C        DISCRETE_INPUT(3)
360
361/* bit mask of the above RC inputs */
362#define DSD_555_MSTBL_RC_MASK   0x0c
363
364DISCRETE_STEP(dsd_555_mstbl)
365{
366   DISCRETE_DECLARE_INFO(discrete_555_desc)
367
368   double v_cap;           /* Current voltage on capacitor, before dt */
369   double x_time = 0;      /* time since change happened */
370   double dt, exponent;
371   double out = 0;
372   int trigger = 0;
373   int trigger_type;
374   int update_exponent = m_has_rc_nodes;
375   int flip_flop;
376
377   if(UNEXPECTED(DSD_555_MSTBL__RESET))
378   {
379      /* We are in RESET */
380      set_output(0, 0);
381      m_flip_flop  = 0;
382      m_cap_voltage = 0;
383      return;
384   }
385
386   dt = this->sample_time();
387   flip_flop = m_flip_flop;
388   trigger_type = info->options;
389   v_cap = m_cap_voltage;
390
391   switch (trigger_type & DSD_555_TRIGGER_TYPE_MASK)
392   {
393      case DISC_555_TRIGGER_IS_LOGIC:
394         trigger = ((int)DSD_555_MSTBL__TRIGGER) ? 0 : 1;
395         if (UNEXPECTED(trigger))
396            x_time = 1.0 - DSD_555_MSTBL__TRIGGER;
397         break;
398      case DISC_555_TRIGGER_IS_VOLTAGE:
399         trigger = (int)(DSD_555_MSTBL__TRIGGER < m_trigger);
400         break;
401      case DISC_555_TRIGGER_IS_COUNT:
402         trigger = (int)DSD_555_MSTBL__TRIGGER;
403         if (UNEXPECTED(trigger))
404            x_time = DSD_555_MSTBL__TRIGGER - trigger;
405         break;
406   }
407
408   if (UNEXPECTED(trigger && !flip_flop && x_time != 0))
409   {
410      /* adjust sample to after trigger */
411      update_exponent = 1;
412      dt *= x_time;
413   }
414   x_time = 0;
415
416   if ((trigger_type & DISC_555_TRIGGER_DISCHARGES_CAP) && trigger)
417      m_cap_voltage = 0;
418
419   /* Wait for trigger */
420   if (UNEXPECTED(!flip_flop && trigger))
421   {
422      flip_flop = 1;
423      m_flip_flop = 1;
424   }
425
426   if (flip_flop)
427   {
428      /* Sometimes a switching network is used to setup the capacitance.
429       * These may select 'no' capacitor, causing oscillation to stop.
430       */
431      if (UNEXPECTED(DSD_555_MSTBL__C == 0))
432      {
433         /* The trigger voltage goes high because the cap circuit is open.
434          * and the cap discharges */
435         v_cap = info->v_pos;    /* needed for cap output type */
436         m_cap_voltage = 0;
437
438         if (!trigger)
439         {
440            flip_flop = 0;
441            m_flip_flop = 0;
442         }
443      }
444      else
445      {
446         /* Charging */
447         double v_diff = m_v_charge - v_cap;
448
449         if (UNEXPECTED(update_exponent))
450            exponent = RC_CHARGE_EXP_DT(DSD_555_MSTBL__R * DSD_555_MSTBL__C, dt);
451         else
452            exponent = m_exp_charge;
453         v_cap += v_diff * exponent;
454
455         /* Has it charged past upper limit? */
456         /* If trigger is still enabled, then we keep charging,
457          * regardless of threshold. */
458         if (UNEXPECTED((v_cap >= m_threshold) && !trigger))
459         {
460            dt = DSD_555_MSTBL__R * DSD_555_MSTBL__C  * log(1.0 / (1.0 - ((v_cap - m_threshold) / v_diff)));
461            x_time = 1.0 - dt / this->sample_time();
462            v_cap  = 0;
463            flip_flop = 0;
464            m_flip_flop = 0;
465         }
466         m_cap_voltage = v_cap;
467      }
468   }
469
470   switch (m_output_type)
471   {
472      case DISC_555_OUT_SQW:
473         out = flip_flop * m_v_out_high - m_ac_shift;
474         break;
475      case DISC_555_OUT_CAP:
476         if (x_time > 0)
477            out = v_cap * x_time;
478         else
479            out = v_cap;
480
481         out -= m_ac_shift;
482         break;
483      case DISC_555_OUT_ENERGY:
484         if (x_time > 0)
485            out = m_v_out_high * x_time;
486         else if (flip_flop)
487            out = m_v_out_high;
488         else
489            out = 0;
490
491         out -= m_ac_shift;
492         break;
493   }
494   set_output(0,  out);
495}
496
497DISCRETE_RESET(dsd_555_mstbl)
498{
499   DISCRETE_DECLARE_INFO(discrete_555_desc)
500
501   m_output_type = info->options & DISC_555_OUT_MASK;
502   if ((m_output_type == DISC_555_OUT_COUNT_F) || (m_output_type == DISC_555_OUT_COUNT_R))
503   {
504      m_device->discrete_log("Invalid Output type in NODE_%d.\n", this->index());
505      m_output_type = DISC_555_OUT_SQW;
506   }
507
508   /* Use the defaults or supplied values. */
509   m_v_out_high = (info->v_out_high == DEFAULT_555_HIGH) ? info->v_pos - 1.2 : info->v_out_high;
510   m_v_charge   = (info->v_charge   == DEFAULT_555_CHARGE) ? info->v_pos : info->v_charge;
511
512   /* Setup based on v_pos power source */
513   m_threshold = info->v_pos * 2.0 / 3.0;
514   m_trigger   = info->v_pos / 3.0;
515
516   /* Calculate DC shift needed to make waveform AC */
517   if (info->options & DISC_555_OUT_AC)
518   {
519      if (m_output_type == DISC_555_OUT_CAP)
520         m_ac_shift = m_threshold * 3.0 /4.0;
521      else
522         m_ac_shift = m_v_out_high / 2.0;
523   }
524   else
525      m_ac_shift = 0;
526
527   m_trig_is_logic       = (info->options & DISC_555_TRIGGER_IS_VOLTAGE) ? 0: 1;
528   m_trig_discharges_cap = (info->options & DISC_555_TRIGGER_DISCHARGES_CAP) ? 1: 0;
529
530   m_flip_flop   = 0;
531   m_cap_voltage = 0;
532
533   /* optimization if none of the values are nodes */
534   m_has_rc_nodes = 0;
535   if (this->input_is_node() & DSD_555_MSTBL_RC_MASK)
536      m_has_rc_nodes = 1;
537   else
538      m_exp_charge = RC_CHARGE_EXP(DSD_555_MSTBL__R * DSD_555_MSTBL__C);
539
540   set_output(0,  0);
541}
542
543
544/************************************************************************
545 *
546 * DSD_555_CC - Usage of node_description values
547 *
548 * input[0]    - Reset input value
549 * input[1]    - Voltage input for Constant current source.
550 * input[2]    - R value to set CC current.
551 * input[3]    - C value
552 * input[4]    - rBias value
553 * input[5]    - rGnd value
554 * input[6]    - rDischarge value
555 *
556 * also passed discrete_555_cc_desc structure
557 *
558 * Mar 2004, D Renaud.
559 ************************************************************************/
560#define DSD_555_CC__RESET   (! DISCRETE_INPUT(0))
561#define DSD_555_CC__VIN     DISCRETE_INPUT(1)
562#define DSD_555_CC__R       DISCRETE_INPUT(2)
563#define DSD_555_CC__C       DISCRETE_INPUT(3)
564#define DSD_555_CC__RBIAS   DISCRETE_INPUT(4)
565#define DSD_555_CC__RGND    DISCRETE_INPUT(5)
566#define DSD_555_CC__RDIS    DISCRETE_INPUT(6)
567
568/* bit mask of the above RC inputs not including DSD_555_CC__R */
569#define DSD_555_CC_RC_MASK  0x78
570
571/* charge/discharge constants */
572#define DSD_555_CC_T_RC_BLEED           (DEFAULT_555_BLEED_R * DSD_555_CC__C)
573#define DSD_555_CC_T_RC_DISCHARGE_01    (DSD_555_CC__RDIS * DSD_555_CC__C)
574#define DSD_555_CC_T_RC_DISCHARGE_NO_I  (DSD_555_CC__RGND * DSD_555_CC__C)
575#define DSD_555_CC_T_RC_CHARGE          (r_charge * DSD_555_CC__C)
576#define DSD_555_CC_T_RC_DISCHARGE       (r_discharge * DSD_555_CC__C)
577
578
579DISCRETE_STEP(dsd_555_cc)
580{
581   DISCRETE_DECLARE_INFO(discrete_555_cc_desc)
582
583   int     count_f  = 0;
584   int     count_r  = 0;
585   double  i;                  /* Charging current created by vIn */
586   double  r_charge = 0;       /* Equivalent charging resistor */
587   double  r_discharge = 0;    /* Equivalent discharging resistor */
588   double  vi     = 0;         /* Equivalent voltage from current source */
589   double  v_bias = 0;         /* Equivalent voltage from bias voltage */
590   double  v      = 0;         /* Equivalent voltage total from current source and bias circuit if used */
591   double  dt;                 /* change in time */
592   double  x_time = 0;         /* time since change happened */
593   double  t_rc ;              /* RC time constant */
594   double  v_cap;              /* Current voltage on capacitor, before dt */
595   double  v_cap_next = 0;     /* Voltage on capacitor, after dt */
596   double  v_vcharge_limit;    /* vIn and the junction voltage limit the max charging voltage from i */
597   double  r_temp;             /* play thing */
598   double  exponent;
599   UINT8   update_exponent, update_t_rc;
600   UINT8   flip_flop = m_flip_flop;
601
602   double v_out = 0;
603
604
605   if (UNEXPECTED(DSD_555_CC__RESET))
606   {
607      /* We are in RESET */
608      set_output(0, 0);
609      m_flip_flop   = 1;
610      m_cap_voltage = 0;
611      return;
612   }
613
614   dt    = this->sample_time();    /* Change in time */
615   v_cap = m_cap_voltage;  /* Set to voltage before change */
616   v_vcharge_limit = DSD_555_CC__VIN + info->v_cc_junction;    /* the max v_cap can be and still be charged by i */
617   /* Calculate charging current */
618   i = (m_v_cc_source - v_vcharge_limit) / DSD_555_CC__R;
619   if ( i < 0) i = 0;
620
621   if (info->options & DISCRETE_555_CC_TO_CAP)
622   {
623      vi = i * DSD_555_CC__RDIS;
624   }
625   else
626   {
627      switch (m_type) /* see dsd_555_cc_reset for descriptions */
628      {
629         case 1:
630            r_discharge = DSD_555_CC__RDIS;
631         case 0:
632            break;
633         case 3:
634            r_discharge = RES_2_PARALLEL(DSD_555_CC__RDIS, DSD_555_CC__RGND);
635         case 2:
636            r_charge = DSD_555_CC__RGND;
637            vi       = i * r_charge;
638            break;
639         case 4:
640            r_charge = DSD_555_CC__RBIAS;
641            vi       = i * r_charge;
642            v_bias   = info->v_pos;
643            break;
644         case 5:
645            r_charge = DSD_555_CC__RBIAS + DSD_555_CC__RDIS;
646            vi      = i * DSD_555_CC__RBIAS;
647            v_bias  = info->v_pos;
648            r_discharge = DSD_555_CC__RDIS;
649            break;
650         case 6:
651            r_charge = RES_2_PARALLEL(DSD_555_CC__RBIAS, DSD_555_CC__RGND);
652            vi      = i * r_charge;
653            v_bias  = info->v_pos * RES_VOLTAGE_DIVIDER(DSD_555_CC__RGND, DSD_555_CC__RBIAS);
654            break;
655         case 7:
656            r_temp   = DSD_555_CC__RBIAS + DSD_555_CC__RDIS;
657            r_charge = RES_2_PARALLEL(r_temp, DSD_555_CC__RGND);
658            r_temp  += DSD_555_CC__RGND;
659            r_temp   = DSD_555_CC__RGND / r_temp;   /* now has voltage divider ratio, not resistance */
660            vi      = i * DSD_555_CC__RBIAS * r_temp;
661            v_bias  = info->v_pos * r_temp;
662            r_discharge = RES_2_PARALLEL(DSD_555_CC__RGND, DSD_555_CC__RDIS);
663            break;
664      }
665   }
666
667   /* Keep looping until all toggling in time sample is used up. */
668   update_t_rc = m_has_rc_nodes;
669   update_exponent = update_t_rc;
670   do
671   {
672      if (m_type <= 1)
673      {
674         /* Standard constant current charge */
675         if (flip_flop)
676         {
677            if (i == 0)
678            {
679               /* No charging current, so we have to discharge the cap
680                * due to cap and circuit losses.
681                */
682               if (update_exponent)
683               {
684                  t_rc     = DSD_555_CC_T_RC_BLEED;
685                  exponent = RC_CHARGE_EXP_DT(t_rc, dt);
686               }
687               else
688                  exponent = m_exp_bleed;
689               v_cap_next = v_cap - (v_cap * exponent);
690               dt = 0;
691            }
692            else
693            {
694               /* Charging */
695               /* iC=C*dv/dt  works out to dv=iC*dt/C */
696               v_cap_next = v_cap + (i * dt / DSD_555_CC__C);
697               /* Yes, if the cap voltage has reached the max voltage it can,
698                * and the 555 threshold has not been reached, then oscillation stops.
699                * This is the way the actual electronics works.
700                * This is why you never play with the pots after being factory adjusted
701                * to work in the proper range. */
702               if (v_cap_next > v_vcharge_limit) v_cap_next = v_vcharge_limit;
703               dt = 0;
704
705               /* has it charged past upper limit? */
706               if (v_cap_next >= m_threshold)
707               {
708                  /* calculate the overshoot time */
709                  dt     = DSD_555_CC__C * (v_cap_next - m_threshold) / i;
710                  x_time = dt;
711                  v_cap_next = m_threshold;
712                  flip_flop = 0;
713                  count_f++;
714                  update_exponent = 1;
715               }
716            }
717         }
718         else if (DSD_555_CC__RDIS != 0)
719         {
720            /* Discharging */
721            if (update_t_rc)
722               t_rc = DSD_555_CC_T_RC_DISCHARGE_01;
723            else
724               t_rc = m_t_rc_discharge_01;
725            if (update_exponent)
726               exponent = RC_CHARGE_EXP_DT(t_rc, dt);
727            else
728               exponent = m_exp_discharge_01;
729
730            if (info->options & DISCRETE_555_CC_TO_CAP)
731            {
732               /* Asteroids - Special Case */
733               /* Charging in discharge mode */
734               /* If the cap voltage is past the current source charging limit
735                * then only the bias voltage will charge the cap. */
736               v          = (v_cap < v_vcharge_limit) ? vi : v_vcharge_limit;
737               v_cap_next = v_cap + ((v - v_cap) * exponent);
738            }
739            else
740            {
741               v_cap_next = v_cap - (v_cap * exponent);
742            }
743
744            dt = 0;
745            /* has it discharged past lower limit? */
746            if (v_cap_next <= m_trigger)
747            {
748               dt     = t_rc  * log(1.0 / (1.0 - ((m_trigger - v_cap_next) / v_cap)));
749               x_time = dt;
750               v_cap_next  = m_trigger;
751               flip_flop = 1;
752               count_r++;
753               update_exponent = 1;
754            }
755         }
756         else    /* Immediate discharge. No change in dt. */
757         {
758            x_time = dt;
759            v_cap_next = m_trigger;
760            flip_flop = 1;
761            count_r++;
762         }
763      }
764      else
765      {
766         /* The constant current gets changed to a voltage due to a load resistor. */
767         if (flip_flop)
768         {
769            if ((i == 0) && (DSD_555_CC__RBIAS == 0))
770            {
771               /* No charging current, so we have to discharge the cap
772                * due to rGnd.
773                */
774               if (update_t_rc)
775                  t_rc = DSD_555_CC_T_RC_DISCHARGE_NO_I;
776               else
777                  t_rc = m_t_rc_discharge_no_i;
778               if (update_exponent)
779                  exponent = RC_CHARGE_EXP_DT(t_rc, dt);
780               else
781                  exponent = m_exp_discharge_no_i;
782
783               v_cap_next = v_cap - (v_cap * exponent);
784               dt = 0;
785            }
786            else
787            {
788               /* Charging */
789               /* If the cap voltage is past the current source charging limit
790                * then only the bias voltage will charge the cap. */
791               v = v_bias;
792               if (v_cap < v_vcharge_limit) v += vi;
793               else if (m_type <= 3) v = v_vcharge_limit;
794
795               if (update_t_rc)
796                  t_rc = DSD_555_CC_T_RC_CHARGE;
797               else
798                  t_rc = m_t_rc_charge;
799               if (update_exponent)
800                  exponent = RC_CHARGE_EXP_DT(t_rc, dt);
801               else
802                  exponent = m_exp_charge;
803
804               v_cap_next = v_cap + ((v - v_cap) * exponent);
805               dt         = 0;
806
807               /* has it charged past upper limit? */
808               if (v_cap_next >= m_threshold)
809               {
810                  /* calculate the overshoot time */
811                  dt     = t_rc  * log(1.0 / (1.0 - ((v_cap_next - m_threshold) / (v - v_cap))));
812                  x_time = dt;
813                  v_cap_next = m_threshold;
814                  flip_flop = 0;
815                  count_f++;
816                  update_exponent = 1;
817               }
818            }
819         }
820         else /* Discharging */
821         if (r_discharge)
822         {
823            if (update_t_rc)
824               t_rc = DSD_555_CC_T_RC_DISCHARGE;
825            else
826               t_rc = m_t_rc_discharge;
827            if (update_exponent)
828               exponent = RC_CHARGE_EXP_DT(t_rc, dt);
829            else
830               exponent = m_exp_discharge;
831
832            v_cap_next = v_cap - (v_cap * exponent);
833            dt = 0;
834
835            /* has it discharged past lower limit? */
836            if (v_cap_next <= m_trigger)
837            {
838               /* calculate the overshoot time */
839               dt     = t_rc  * log(1.0 / (1.0 - ((m_trigger - v_cap_next) / v_cap)));
840               x_time = dt;
841               v_cap_next = m_trigger;
842               flip_flop = 1;
843               count_r++;
844               update_exponent = 1;
845            }
846         }
847         else    /* Immediate discharge. No change in dt. */
848         {
849            x_time = dt;
850            v_cap_next = m_trigger;
851            flip_flop = 1;
852            count_r++;
853         }
854      }
855      v_cap = v_cap_next;
856   } while(dt);
857
858   m_cap_voltage = v_cap;
859
860   /* Convert last switch time to a ratio */
861   x_time = x_time / this->sample_time();
862
863   switch (m_output_type)
864   {
865      case DISC_555_OUT_SQW:
866         if (count_f + count_r >= 2)
867            /* force at least 1 toggle */
868            v_out =  m_flip_flop ? 0 : m_v_out_high;
869         else
870            v_out = flip_flop * m_v_out_high;
871         /* Fake it to AC if needed */
872         v_out += m_ac_shift;
873         break;
874      case DISC_555_OUT_CAP:
875         v_out = v_cap + m_ac_shift;
876         break;
877      case DISC_555_OUT_ENERGY:
878         if (x_time == 0) x_time = 1.0;
879         v_out = m_v_out_high * (flip_flop ? x_time : (1.0 - x_time));
880         v_out += m_ac_shift;
881         break;
882      case DISC_555_OUT_LOGIC_X:
883         v_out = flip_flop + x_time;
884         break;
885      case DISC_555_OUT_COUNT_F_X:
886         v_out = count_f ? count_f + x_time : count_f;
887         break;
888      case DISC_555_OUT_COUNT_R_X:
889         v_out = count_r ? count_r + x_time : count_r;
890         break;
891      case DISC_555_OUT_COUNT_F:
892         v_out = count_f;
893         break;
894      case DISC_555_OUT_COUNT_R:
895         v_out = count_r;
896         break;
897   }
898   set_output(0, v_out);
899   m_flip_flop = flip_flop;
900}
901
902DISCRETE_RESET(dsd_555_cc)
903{
904   DISCRETE_DECLARE_INFO(discrete_555_cc_desc)
905
906   double  r_temp, r_discharge = 0, r_charge = 0;
907
908   m_flip_flop   = 1;
909   m_cap_voltage = 0;
910
911   m_output_type = info->options & DISC_555_OUT_MASK;
912
913   /* Use the defaults or supplied values. */
914   m_v_out_high  = (info->v_out_high  == DEFAULT_555_HIGH) ? info->v_pos - 1.2 : info->v_out_high;
915   m_v_cc_source = (info->v_cc_source == DEFAULT_555_CC_SOURCE) ? info->v_pos : info->v_cc_source;
916
917   /* Setup based on v_pos power source */
918   m_threshold = info->v_pos * 2.0 / 3.0;
919   m_trigger   = info->v_pos / 3.0;
920
921   m_output_is_ac = info->options & DISC_555_OUT_AC;
922   /* Calculate DC shift needed to make squarewave waveform AC */
923   m_ac_shift     = m_output_is_ac ? -m_v_out_high / 2.0 : 0;
924
925   /* There are 8 different types of basic oscillators
926    * depending on the resistors used.  We will determine
927    * the type of circuit at reset, because the ciruit type
928    * is constant.  See Below.
929    */
930   m_type = (DSD_555_CC__RDIS > 0) | ((DSD_555_CC__RGND  > 0) << 1) | ((DSD_555_CC__RBIAS  > 0) << 2);
931
932   /* optimization if none of the values are nodes */
933   m_has_rc_nodes = 0;
934   if (this->input_is_node() & DSD_555_CC_RC_MASK)
935      m_has_rc_nodes = 1;
936   else
937   {
938      switch (m_type) /* see dsd_555_cc_reset for descriptions */
939      {
940         case 1:
941            r_discharge = DSD_555_CC__RDIS;
942         case 0:
943            break;
944         case 3:
945            r_discharge = RES_2_PARALLEL(DSD_555_CC__RDIS, DSD_555_CC__RGND);
946         case 2:
947            r_charge = DSD_555_CC__RGND;
948            break;
949         case 4:
950            r_charge = DSD_555_CC__RBIAS;
951            break;
952         case 5:
953            r_charge = DSD_555_CC__RBIAS + DSD_555_CC__RDIS;
954            r_discharge = DSD_555_CC__RDIS;
955            break;
956         case 6:
957            r_charge = RES_2_PARALLEL(DSD_555_CC__RBIAS, DSD_555_CC__RGND);
958            break;
959         case 7:
960            r_temp   = DSD_555_CC__RBIAS + DSD_555_CC__RDIS;
961            r_charge = RES_2_PARALLEL(r_temp, DSD_555_CC__RGND);
962            r_discharge = RES_2_PARALLEL(DSD_555_CC__RGND, DSD_555_CC__RDIS);
963            break;
964      }
965
966      m_exp_bleed  = RC_CHARGE_EXP(DSD_555_CC_T_RC_BLEED);
967      m_t_rc_discharge_01 = DSD_555_CC_T_RC_DISCHARGE_01;
968      m_exp_discharge_01  = RC_CHARGE_EXP(m_t_rc_discharge_01);
969      m_t_rc_discharge_no_i = DSD_555_CC_T_RC_DISCHARGE_NO_I;
970      m_exp_discharge_no_i  = RC_CHARGE_EXP(m_t_rc_discharge_no_i);
971      m_t_rc_charge = DSD_555_CC_T_RC_CHARGE;
972      m_exp_charge  = RC_CHARGE_EXP(m_t_rc_charge);
973      m_t_rc_discharge = DSD_555_CC_T_RC_DISCHARGE;
974      m_exp_discharge  = RC_CHARGE_EXP(m_t_rc_discharge);
975   }
976
977   /* Step to set the output */
978   this->step();
979
980   /*
981    * TYPES:
982    * Note: These are equivalent circuits shown without the 555 circuitry.
983    *       See the schematic in src\sound\discrete.h for full hookup info.
984    *
985    * DISCRETE_555_CC_TO_DISCHARGE_PIN
986    * When the CC source is connected to the discharge pin, it allows the
987    * circuit to charge when the 555 is in charge mode.  But when in discharge
988    * mode, the CC source is grounded, disabling it's effect.
989    *
990    * [0]
991    * No resistors.  Straight constant current charge of capacitor.
992    * When there is not any charge current, the cap will bleed off.
993    * Once the lower threshold(trigger) is reached, the output will
994    * go high but the cap will continue to discharge due to losses.
995    *   .------+---> cap_voltage      CHARGING:
996    *   |      |                 dv (change in voltage) compared to dt (change in time in seconds).
997    * .---.   ---                dv = i * dt / C; where i is current in amps and C is capacitance in farads.
998    * | i |   --- C              cap_voltage = cap_voltage + dv
999    * '---'    |
1000    *   |      |               DISCHARGING:
1001    *  gnd    gnd                instantaneous
1002    *
1003    * [1]
1004    * Same as type 1 but with rDischarge.  rDischarge has no effect on the charge rate because
1005    * of the constant current source i.
1006    * When there is not any charge current, the cap will bleed off.
1007    * Once the lower threshold(trigger) is reached, the output will
1008    * go high but the cap will continue to discharge due to losses.
1009    *   .----ZZZ-----+---> cap_voltage      CHARGING:
1010    *   | rDischarge |                 dv (change in voltage) compared to dt (change in time in seconds).
1011    * .---.         ---                dv = i * dt / C; where i is current in amps and C is capacitance in farads.
1012    * | i |         --- C              cap_voltage = cap_voltage + dv
1013    * '---'          |
1014    *   |            |               DISCHARGING:
1015    *  gnd          gnd                through rDischarge
1016    *
1017    * !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
1018    * !!!!! IMPORTANT NOTE ABOUT TYPES 3 - 7 !!!!!
1019    * !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
1020    *
1021    * From here on in all the circuits have either an rBias or rGnd resistor.
1022    * This converts the constant current into a voltage source.
1023    * So all the remaining circuit types will be converted to this circuit.
1024    * When discharging, rBias is out of the equation because the 555 is grounding the circuit
1025    * after that point.
1026    *
1027    * .------------.     Rc                  Rc is the equivilent circuit resistance.
1028    * |     v      |----ZZZZ---+---> cap_voltage    v  is the equivilent circuit voltage.
1029    * |            |           |
1030    * '------------'          ---            Then the standard RC charging formula applies.
1031    *       |                 --- C
1032    *       |                  |             NOTE: All the following types are converted to Rc and v values.
1033    *      gnd                gnd
1034    *
1035    * [2]
1036    * When there is not any charge current, the cap will bleed off.
1037    * Once the lower threshold(trigger) is reached, the output will
1038    * go high but the cap will continue to discharge due to rGnd.
1039    *   .-------+------+------> cap_voltage         CHARGING:
1040    *   |       |      |                       v = vi = i * rGnd
1041    * .---.    ---     Z                       Rc = rGnd
1042    * | i |    --- C   Z rGnd
1043    * '---'     |      |                     DISCHARGING:
1044    *   |       |      |                       instantaneous
1045    *  gnd     gnd    gnd
1046    *
1047    * [3]
1048    * When there is not any charge current, the cap will bleed off.
1049    * Once the lower threshold(trigger) is reached, the output will
1050    * go high but the cap will continue to discharge due to rGnd.
1051    *   .----ZZZ-----+------+------> cap_voltage    CHARGING:
1052    *   | rDischarge |      |                  v = vi = i * rGnd
1053    * .---.         ---     Z                  Rc = rGnd
1054    * | i |         --- C   Z rGnd
1055    * '---'          |      |                DISCHARGING:
1056    *   |            |      |                  through rDischarge || rGnd  ( || means in parallel)
1057    *  gnd          gnd    gnd
1058    *
1059    * [4]
1060    *     .---ZZZ---+------------+-------------> cap_voltage      CHARGING:
1061    *     |  rBias  |            |                           Rc = rBias
1062    * .-------.   .---.         ---                          vi = i * rBias
1063    * | vBias |   | i |         --- C                        v = vBias + vi
1064    * '-------'   '---'          |
1065    *     |         |            |                         DISCHARGING:
1066    *    gnd       gnd          gnd                          instantaneous
1067    *
1068    * [5]
1069    *     .---ZZZ---+----ZZZ-----+-------------> cap_voltage      CHARGING:
1070    *     |  rBias  | rDischarge |                           Rc = rBias + rDischarge
1071    * .-------.   .---.         ---                          vi = i * rBias
1072    * | vBias |   | i |         --- C                        v = vBias + vi
1073    * '-------'   '---'          |
1074    *     |         |            |                         DISCHARGING:
1075    *    gnd       gnd          gnd                          through rDischarge
1076    *
1077    * [6]
1078    *     .---ZZZ---+------------+------+------> cap_voltage      CHARGING:
1079    *     |  rBias  |            |      |                    Rc = rBias || rGnd
1080    * .-------.   .---.         ---     Z                    vi = i * Rc
1081    * | vBias |   | i |         --- C   Z rGnd               v = vBias * (rGnd / (rBias + rGnd)) + vi
1082    * '-------'   '---'          |      |
1083    *     |         |            |      |                  DISCHARGING:
1084    *    gnd       gnd          gnd    gnd                   instantaneous
1085    *
1086    * [7]
1087    *     .---ZZZ---+----ZZZ-----+------+------> cap_voltage      CHARGING:
1088    *     |  rBias  | rDischarge |      |                    Rc = (rBias + rDischarge) || rGnd
1089    * .-------.   .---.         ---     Z                    vi = i * rBias * (rGnd / (rBias + rDischarge + rGnd))
1090    * | vBias |   | i |         --- C   Z rGnd               v = vBias * (rGnd / (rBias + rDischarge + rGnd)) + vi
1091    * '-------'   '---'          |      |
1092    *     |         |            |      |                  DISCHARGING:
1093    *    gnd       gnd          gnd    gnd                   through rDischarge || rGnd
1094    */
1095
1096   /*
1097    * DISCRETE_555_CC_TO_CAP
1098    *
1099    * When the CC source is connected to the capacitor, it allows the
1100    * current to charge the cap while it is in discharge mode, slowing the
1101    * discharge.  So in charge mode it charges linearly from the constant
1102    * current cource.  But when in discharge mode it behaves like circuit
1103    * type 2 above.
1104    *   .-------+------+------> cap_voltage         CHARGING:
1105    *   |       |      |                       dv = i * dt / C
1106    * .---.    ---     Z                       cap_voltage = cap_voltage + dv
1107    * | i |    --- C   Z rDischarge
1108    * '---'     |      |                     DISCHARGING:
1109    *   |       |      |                       v = vi = i * rGnd
1110    *  gnd     gnd   discharge                 Rc = rDischarge
1111    */
1112}
1113
1114
1115/************************************************************************
1116 *
1117 * DSD_555_VCO1 - Usage of node_description values
1118 *
1119 * input[0]    - Reset input value
1120 * input[1]    - Modulation Voltage (Vin1)
1121 * input[2]    - Control Voltage (Vin2)
1122 *
1123 * also passed discrete_5555_vco1_desc structure
1124 *
1125 * Apr 2006, D Renaud.
1126 ************************************************************************/
1127#define DSD_555_VCO1__RESET DISCRETE_INPUT(0)   /* reset active low */
1128#define DSD_555_VCO1__VIN1  DISCRETE_INPUT(1)
1129#define DSD_555_VCO1__VIN2  DISCRETE_INPUT(2)
1130
1131DISCRETE_STEP(dsd_555_vco1)
1132{
1133   DISCRETE_DECLARE_INFO(discrete_555_vco1_desc)
1134
1135   int     count_f = 0;
1136   int     count_r = 0;
1137   double  dt;             /* change in time */
1138   double  x_time  = 0;    /* time since change happened */
1139   double  v_cap;          /* Current voltage on capacitor, before dt */
1140   double  v_cap_next = 0; /* Voltage on capacitor, after dt */
1141
1142   double  v_out = 0;
1143
1144   dt    = this->sample_time();    /* Change in time */
1145   v_cap = m_cap_voltage;
1146
1147   /* Check: if the Control Voltage node is connected. */
1148   if (m_ctrlv_is_node && DSD_555_VCO1__RESET) /* reset active low */
1149   {
1150      /* If CV is less then .25V, the circuit will oscillate way out of range.
1151       * So we will just ignore it when it happens. */
1152      if (DSD_555_VCO1__VIN2 < .25) return;
1153      /* If it is a node then calculate thresholds based on Control Voltage */
1154      m_threshold = DSD_555_VCO1__VIN2;
1155      m_trigger   = DSD_555_VCO1__VIN2 / 2.0;
1156      /* Since the thresholds may have changed we need to update the FF */
1157      if (v_cap >= m_threshold)
1158      {
1159         x_time = dt;
1160         m_flip_flop = 0;
1161         count_f++;
1162      }
1163      else
1164      if (v_cap <= m_trigger)
1165      {
1166         x_time = dt;
1167         m_flip_flop = 1;
1168         count_r++;
1169      }
1170   }
1171
1172   /* Keep looping until all toggling in time sample is used up. */
1173   do
1174   {
1175      if (m_flip_flop)
1176      {
1177         /* if we are in reset then toggle f/f and discharge */
1178         if (!DSD_555_VCO1__RESET)   /* reset active low */
1179         {
1180            m_flip_flop = 0;
1181            count_f++;
1182         }
1183         else
1184         {
1185            /* Charging */
1186            /* iC=C*dv/dt  works out to dv=iC*dt/C */
1187            v_cap_next = v_cap + (m_i_charge * dt / info->c);
1188            dt         = 0;
1189
1190            /* has it charged past upper limit? */
1191            if (v_cap_next >= m_threshold)
1192            {
1193               /* calculate the overshoot time */
1194               dt     = info->c * (v_cap_next - m_threshold) / m_i_charge;
1195               v_cap  = m_threshold;
1196               x_time = dt;
1197               m_flip_flop = 0;
1198               count_f++;
1199            }
1200         }
1201      }
1202      else
1203      {
1204         /* Discharging */
1205         /* iC=C*dv/dt  works out to dv=iC*dt/C */
1206         v_cap_next = v_cap - (m_i_discharge * dt / info->c);
1207
1208         /* if we are in reset, then the cap can discharge to 0 */
1209         if (!DSD_555_VCO1__RESET)   /* reset active low */
1210         {
1211            if (v_cap_next < 0) v_cap_next = 0;
1212            dt = 0;
1213         }
1214         else
1215         {
1216            /* if we are out of reset and the cap voltage is less then
1217             * the lower threshold, toggle f/f and start charging */
1218            if (v_cap <= m_trigger)
1219            {
1220               if (m_flip_flop == 0)
1221               {
1222                  /* don't need to track x_time here */
1223                  m_flip_flop = 1;
1224                  count_r++;
1225               }
1226            }
1227            else
1228            {
1229               dt = 0;
1230               /* has it discharged past lower limit? */
1231               if (v_cap_next <= m_trigger)
1232               {
1233                  /* calculate the overshoot time */
1234                  dt     = info->c * (v_cap_next - m_trigger) / m_i_discharge;
1235                  v_cap  = m_trigger;
1236                  x_time = dt;
1237                  m_flip_flop = 1;
1238                  count_r++;
1239               }
1240            }
1241         }
1242      }
1243   } while(dt);
1244
1245   m_cap_voltage = v_cap_next;
1246
1247   /* Convert last switch time to a ratio.  No x_time in reset. */
1248   x_time = x_time / this->sample_time();
1249   if (!DSD_555_VCO1__RESET) x_time = 0;
1250
1251   switch (m_output_type)
1252   {
1253      case DISC_555_OUT_SQW:
1254         v_out = m_flip_flop * m_v_out_high + m_ac_shift;
1255         break;
1256      case DISC_555_OUT_CAP:
1257         v_out = v_cap_next;
1258         /* Fake it to AC if needed */
1259         if (m_output_is_ac)
1260            v_out -= m_threshold * 3.0 /4.0;
1261         break;
1262      case DISC_555_OUT_ENERGY:
1263         if (x_time == 0) x_time = 1.0;
1264         v_out =  m_v_out_high * (m_flip_flop ? x_time : (1.0 - x_time));
1265         v_out += m_ac_shift;
1266         break;
1267      case DISC_555_OUT_LOGIC_X:
1268         v_out = m_flip_flop + x_time;
1269         break;
1270      case DISC_555_OUT_COUNT_F_X:
1271         v_out = count_f ? count_f + x_time : count_f;
1272         break;
1273      case DISC_555_OUT_COUNT_R_X:
1274         v_out = count_r ? count_r + x_time : count_r;
1275         break;
1276      case DISC_555_OUT_COUNT_F:
1277         v_out = count_f;
1278         break;
1279      case DISC_555_OUT_COUNT_R:
1280         v_out = count_r;
1281         break;
1282   }
1283   set_output(0, v_out);
1284}
1285
1286DISCRETE_RESET(dsd_555_vco1)
1287{
1288   DISCRETE_DECLARE_INFO(discrete_555_vco1_desc)
1289
1290   double v_ratio_r3, v_ratio_r4_1, r_in_1;
1291
1292   m_output_type  = info->options & DISC_555_OUT_MASK;
1293   m_output_is_ac = info->options & DISC_555_OUT_AC;
1294
1295   /* Setup op-amp parameters */
1296
1297   /* The voltage at op-amp +in is always a fixed ratio of the modulation voltage. */
1298   v_ratio_r3 = info->r3 / (info->r2 + info->r3);          /* +in voltage */
1299   /* The voltage at op-amp -in is 1 of 2 fixed ratios of the modulation voltage,
1300    * based on the 555 Flip-Flop state. */
1301   /* If the FF is 0, then only R1 is connected allowing the full modulation volatge to pass. */
1302   /* v_ratio_r4_0 = 1 */
1303   /* If the FF is 1, then R1 & R4 make a voltage divider similar to R2 & R3 */
1304   v_ratio_r4_1 = info->r4 / (info->r1 + info->r4);        /* -in voltage */
1305   /* the input resistance to the op amp depends on the FF state */
1306   /* r_in_0 = info->r1 when FF = 0 */
1307   r_in_1 = 1.0 / (1.0 / info->r1 + 1.0 / info->r4);   /* input resistance when r4 switched in */
1308
1309   /* Now that we know the voltages entering the op amp and the resistance for the
1310    * FF states, we can predetermine the ratios for the charge/discharge currents. */
1311   m_i_discharge = (1 - v_ratio_r3) / info->r1;
1312   m_i_charge    = (v_ratio_r3 - v_ratio_r4_1) / r_in_1;
1313
1314   /* the cap starts off discharged */
1315   m_cap_voltage = 0;
1316
1317   /* Setup 555 parameters */
1318
1319   /* There is no charge on the cap so the 555 goes high at init. */
1320   m_flip_flop     = 1;
1321   m_ctrlv_is_node = (this->input_is_node() >> 2) & 1;
1322   m_v_out_high    = (info->v_out_high == DEFAULT_555_HIGH) ? info->v_pos - 1.2 : info->v_out_high;
1323
1324   /* Calculate 555 thresholds.
1325    * If the Control Voltage is a node, then the thresholds will be calculated each step.
1326    * If the Control Voltage is a fixed voltage, then the thresholds will be calculated
1327    * from that.  Otherwise we will use thresholds based on v_pos. */
1328   if (!m_ctrlv_is_node && (DSD_555_VCO1__VIN2 != -1))
1329   {
1330      /* Setup based on supplied Control Voltage static value */
1331      m_threshold = DSD_555_VCO1__VIN2;
1332      m_trigger   = DSD_555_VCO1__VIN2 / 2.0;
1333   }
1334   else
1335   {
1336      /* Setup based on v_pos power source */
1337      m_threshold = info->v_pos * 2.0 / 3.0;
1338      m_trigger   = info->v_pos / 3.0;
1339   }
1340
1341   /* Calculate DC shift needed to make squarewave waveform AC */
1342   m_ac_shift = m_output_is_ac ? -m_v_out_high / 2.0 : 0;
1343}
1344
1345
1346/************************************************************************
1347 *
1348 * DSD_566 - Usage of node_description values
1349 *
1350 * Mar 2004, D Renaud. updated Sept 2009
1351 *
1352 * The data sheets for this are no where near correct.
1353 * This simulation is based on the internal schematic and testing of
1354 * a real Signetics IC.
1355 *
1356 * The 566 is a constant current based VCO.  If you change R, that affects
1357 * the charge/discharge rate.  A constant current source will charge the
1358 * cap linearly.  Of course due to the transistors there will be some
1359 * non-linear areas at the ends of the Vmod range.  As the Vmod voltage
1360 * drops from Vcharge, the frequency generated increases.
1361 *
1362 * The Triangle (pin 4) output is just a buffered version of the cap
1363 * charge.  It is about 1.35 higher then the cap voltage.
1364 * The Square (pin 3) output starts low as the cap voltages rises.
1365 * Once a threshold is reached, the cap starts to discharge, and the
1366 * Square output goes high.  The Square high output is about 1V less then
1367 * B+.  Unloaded it is .75V less.  With a 4.7k pull-down resistor, it
1368 * is 1.06V less.  So I will simulate at 1V less. The Square low voltage
1369 * is non-linear so I will use a table.  The cap toggle thresholds vary
1370 * depending on B+, so they will be simulated with a table.
1371 *
1372 * The data sheets show Vmod should be no less then 3/4*B+.  In reality
1373 * you can go to close to 1/2*B+ before you lose linearity.  Below 1/2,
1374 * oscillation stops.  When Vmod is 0V to 0.1V less then B+, it also
1375 * loses linearity, and stops oscillating when >= B+.  This is because
1376 * there is no voltage difference to create a current source.
1377 *
1378 * The current source is dependant on the voltage difference between B+
1379 * and Vmod.  Due to transistor action, it is not 100%, but this formula
1380 * gives a good approximation:
1381 * I = ((B+ - Vmod - 0.1) * 0.95) / R
1382 * You can test the current VS modulation function by using 10k for R
1383 * and replace C with a 10k resistor.  Then you can monitor the voltage
1384 * on pin 7 to work out the current.  I=V/R.  It will start to oscillate
1385 * when in the cap threshold range.
1386 *
1387 * When Vmod drops below the stable range, the current source no longer
1388 * functions properly.  Technically this is out of the range specified
1389 * for the IC.  Of course old games used this range anyways, so we need
1390 * to know how the real IC behaves.  When Vmod drops below the stable range,
1391 * the charge current is stops dropping instead of increasing, while the
1392 * discharge current still functions.  This means the frequency generated
1393 * starts to drop as the voltage lowers, instead of the normal increase
1394 * in frequency.
1395 *
1396 ************************************************************************/
1397#define DSD_566__VMOD       DISCRETE_INPUT(0)
1398#define DSD_566__R          DISCRETE_INPUT(1)
1399#define DSD_566__C          DISCRETE_INPUT(2)
1400#define DSD_566__VPOS       DISCRETE_INPUT(3)
1401#define DSD_566__VNEG       DISCRETE_INPUT(4)
1402#define DSD_566__VCHARGE    DISCRETE_INPUT(5)
1403#define DSD_566__OPTIONS    DISCRETE_INPUT(6)
1404
1405
1406static const struct
1407{
1408   double  c_high[6];
1409   double  c_low[6];
1410   double  sqr_low[6];
1411   double  osc_stable[6];
1412   double  osc_stop[6];
1413} ne566 =
1414{
1415   /* 10      10.5      11      11.5      12     13     14     15             B+ */
1416   {3.364, /*3.784,*/ 4.259, /*4.552,*/ 4.888, 5.384, 5.896, 6.416},       /* c_high */
1417   {1.940, /*2.100,*/ 2.276, /*2.404,*/ 2.580, 2.880, 3.180, 3.488},       /* c_low */
1418   {4.352, /*4.144,*/ 4.080, /*4.260,*/ 4.500, 4.960, 5.456, 5.940},       /* sqr_low */
1419   {4.885, /*5.316,*/ 5.772, /*6.075,*/ 6.335, 6.912, 7.492, 7.945},       /* osc_stable */
1420   {4.495, /*4.895,*/ 5.343, /*5.703,*/ 5.997, 6.507, 7.016, 7.518}        /* osc_stop */
1421};
1422
1423DISCRETE_STEP(dsd_566)
1424{
1425   double  i = 0;          /* Charging current created by vIn */
1426   double  i_rise;         /* non-linear rise charge current */
1427   double  dt;             /* change in time */
1428   double  x_time = 0;
1429   double  v_cap;          /* Current voltage on capacitor, before dt */
1430   int     count_f = 0, count_r = 0;
1431
1432   double  v_out = 0.0;
1433
1434   dt    = this->sample_time();    /* Change in time */
1435   v_cap = m_cap_voltage;  /* Set to voltage before change */
1436
1437   /* Calculate charging current if it is in range */
1438   if (EXPECTED(DSD_566__VMOD > m_v_osc_stop))
1439   {
1440      double v_charge = DSD_566__VCHARGE - DSD_566__VMOD - 0.1;
1441      if (v_charge > 0)
1442      {
1443         i = (v_charge * .95) / DSD_566__R;
1444         if (DSD_566__VMOD < m_v_osc_stable)
1445         {
1446            /* no where near correct calculation of non linear range */
1447            i_rise = ((DSD_566__VCHARGE - m_v_osc_stable - 0.1) * .95) / DSD_566__R;
1448            i_rise *= 1.0 - (m_v_osc_stable - DSD_566__VMOD) / (m_v_osc_stable - m_v_osc_stop);
1449         }
1450         else
1451            i_rise = i;
1452      }
1453      else
1454         return;
1455   }
1456   else return;
1457
1458   /* Keep looping until all toggling in this time sample is used up. */
1459   do
1460   {
1461      if (m_flip_flop)
1462      {
1463         /* Discharging */
1464         v_cap -= i * dt / DSD_566__C;
1465         dt     = 0;
1466
1467         /* has it discharged past lower limit? */
1468         if (UNEXPECTED(v_cap < m_threshold_low))
1469         {
1470            /* calculate the overshoot time */
1471            dt = DSD_566__C * (m_threshold_low - v_cap) / i;
1472            v_cap = m_threshold_low;
1473            m_flip_flop = 0;
1474            count_f++;
1475            x_time = dt;
1476         }
1477      }
1478      else
1479      {
1480         /* Charging */
1481         /* iC=C*dv/dt  works out to dv=iC*dt/C */
1482         v_cap += i_rise * dt / DSD_566__C;
1483         dt     = 0;
1484         /* Yes, if the cap voltage has reached the max voltage it can,
1485          * and the 566 threshold has not been reached, then oscillation stops.
1486          * This is the way the actual electronics works.
1487          * This is why you never play with the pots after being factory adjusted
1488          * to work in the proper range. */
1489         if (UNEXPECTED(v_cap > DSD_566__VMOD)) v_cap = DSD_566__VMOD;
1490
1491         /* has it charged past upper limit? */
1492         if (UNEXPECTED(v_cap > m_threshold_high))
1493         {
1494            /* calculate the overshoot time */
1495            dt = DSD_566__C * (v_cap - m_threshold_high) / i;
1496            v_cap = m_threshold_high;
1497            m_flip_flop = 1;
1498            count_r++;
1499            x_time = dt;
1500         }
1501      }
1502   } while(dt);
1503
1504   m_cap_voltage = v_cap;
1505
1506   /* Convert last switch time to a ratio */
1507   x_time /= this->sample_time();
1508
1509   switch (m_out_type)
1510   {
1511      case DISC_566_OUT_SQUARE:
1512         v_out = m_flip_flop ? m_v_sqr_high : m_v_sqr_low;
1513         if (m_fake_ac)
1514            v_out += m_ac_shift;
1515         break;
1516      case DISC_566_OUT_ENERGY:
1517         if (x_time == 0) x_time = 1.0;
1518         v_out = m_v_sqr_low + m_v_sqr_diff * (m_flip_flop ? x_time : (1.0 - x_time));
1519         if (m_fake_ac)
1520            v_out += m_ac_shift;
1521         break;
1522      case DISC_566_OUT_LOGIC:
1523         v_out = m_flip_flop;
1524         break;
1525      case DISC_566_OUT_TRIANGLE:
1526         v_out = v_cap;
1527         if (m_fake_ac)
1528            v_out += m_ac_shift;
1529         break;
1530      case DISC_566_OUT_COUNT_F_X:
1531         v_out = count_f ? count_f + x_time : count_f;
1532         break;
1533      case DISC_566_OUT_COUNT_R_X:
1534         v_out = count_r ? count_r + x_time : count_r;
1535         break;
1536      case DISC_566_OUT_COUNT_F:
1537         v_out = count_f;
1538         break;
1539      case DISC_566_OUT_COUNT_R:
1540         v_out = count_r;
1541         break;
1542   }
1543   set_output(0, v_out);
1544}
1545
1546DISCRETE_RESET(dsd_566)
1547{
1548   int     v_int;
1549   double  v_float;
1550
1551   m_out_type = (int)DSD_566__OPTIONS & DISC_566_OUT_MASK;
1552   m_fake_ac =  (int)DSD_566__OPTIONS & DISC_566_OUT_AC;
1553
1554   if (DSD_566__VNEG >= DSD_566__VPOS)
1555      fatalerror("[v_neg >= v_pos] in NODE_%d!\n", this->index());
1556
1557   v_float = DSD_566__VPOS - DSD_566__VNEG;
1558   v_int = (int)v_float;
1559   if ( v_float < 10 || v_float > 15 )
1560      fatalerror("v_neg and/or v_pos out of range in NODE_%d\n", this->index());
1561   if ( v_float != v_int )
1562      /* fatal for now. */
1563      fatalerror("Power should be integer in NODE_%d\n", this->index());
1564
1565   m_flip_flop   = 0;
1566   m_cap_voltage = 0;
1567
1568   v_int -= 10;
1569   m_threshold_high = ne566.c_high[v_int] + DSD_566__VNEG;
1570   m_threshold_low  = ne566.c_low[v_int] + DSD_566__VNEG;
1571   m_v_sqr_high     = DSD_566__VPOS - 1;
1572   m_v_sqr_low      = ne566.sqr_low[v_int] + DSD_566__VNEG;
1573   m_v_sqr_diff     = m_v_sqr_high - m_v_sqr_low;
1574   m_v_osc_stable  = ne566.osc_stable[v_int] + DSD_566__VNEG;
1575   m_v_osc_stop        = ne566.osc_stop[v_int] + DSD_566__VNEG;
1576
1577   m_ac_shift = 0;
1578   if (m_fake_ac)
1579   {
1580      if (m_out_type == DISC_566_OUT_TRIANGLE)
1581         m_ac_shift = (m_threshold_high - m_threshold_low) / 2 - m_threshold_high;
1582      else
1583         m_ac_shift = m_v_sqr_diff / 2 - m_v_sqr_high;
1584   }
1585
1586   /* Step the output */
1587   this->step();
1588}
1589
1590
1591/************************************************************************
1592 *
1593 * DSD_LS624 - Usage of node_description values
1594 *
1595 * Dec 2007, Couriersud based on data sheet
1596 * Oct 2009, complete re-write based on IC testing
1597 ************************************************************************/
1598#define DSD_LS624__ENABLE       DISCRETE_INPUT(0)
1599#define DSD_LS624__VMOD         DISCRETE_INPUT(1)
1600#define DSD_LS624__VRNG         DISCRETE_INPUT(2)
1601#define DSD_LS624__C            DISCRETE_INPUT(3)
1602#define DSD_LS624__R_FREQ_IN    DISCRETE_INPUT(4)
1603#define DSD_LS624__C_FREQ_IN    DISCRETE_INPUT(5)
1604#define DSD_LS624__R_RNG_IN     DISCRETE_INPUT(6)
1605#define DSD_LS624__OUTTYPE      DISCRETE_INPUT(7)
1606
1607#define LS624_R_EXT         600.0       /* as specified in data sheet */
1608#define LS624_OUT_HIGH      4.5         /* measured */
1609#define LS624_IN_R      RES_K(90)   /* measured & 70K + 20k per data sheet */
1610
1611/*
1612 * The 74LS624 series are constant current based VCOs.  The Freq Control voltage
1613 * modulates the current source.  The current is created from Rext, which is
1614 * internally fixed at 600 ohms for all devices except the 74LS628 which has
1615 * external connections.  The current source linearly discharges the cap voltage.
1616 * The cap starts with 0V charge across it.  One side is connected to a fixed voltage
1617 * bias circuit.  The other side is charged negatively from the current source until
1618 * a certain low threshold is reached.  Once this threshold is reached, the output
1619 * toggles state and the pins on the cap reverse in respect to the charge/bias hookup.
1620 * This starts the one side of the cap to be at bias, and the other side of the cap is
1621 * now at bias + the charge on the cap which is bias - threshold.
1622 * Y = 0;  CX1 = bias;    CX2 = charge
1623 * Y = 1;  CX1 = charge;  CX2 = bias
1624 * The Range voltage adjusts the threshold voltage.  The higher the Range voltage,
1625 * the lower the threshold voltage, the longer the cap can charge, the lower the frequency.
1626 *
1627 * In a perfect world it would work like this:
1628 * The current is based on the mysterious Rext mentioned in the data sheet.
1629 * I = (VfreqControl  * 20k/90k) / Rext
1630 * where Rext = 600 ohms or external Rext on a 74LS628
1631 * The Freq Control has an input impedance of approximately 90k, so any input resistance
1632 * connected to the Freq Control pin works as a voltage divider.
1633 * I = (VfreqControl * 20k/(90k + RfreqControlIn)) / Rext
1634 * That gives us a change in voltage on the cap of
1635 * dV = I / sampleRate / C_inFarads
1636 *
1637 * Unfortunately the chip does not behave linearly do to internal interactions,
1638 * so I have just worked out the formula (using zunzun.com) of FreqControl and
1639 * range to frequency out for a fixed cap value of 0.1uf.  Other cap values can just
1640 * scale from that.  From the freq, we calculate the time of 1/2 cycle using 1/Freq/2.
1641 * Then just use that to toggle a waveform.
1642 */
1643
1644
1645DISCRETE_STEP(dsd_ls624)
1646{
1647   double  x_time = 0;
1648   double  freq, t1;
1649   double  v_freq_2, v_freq_3, v_freq_4;
1650   double  t_used = m_t_used;
1651   double  dt = this->sample_time();;
1652   double  v_freq = DSD_LS624__VMOD;
1653   double  v_rng = DSD_LS624__VRNG;
1654   int     count_f = 0, count_r = 0;
1655
1656   /* coefficients */
1657   const double k1 = 1.9904769024796283E+03;
1658   const double k2 = 1.2070059213983407E+03;
1659   const double k3 = 1.3266985579561108E+03;
1660   const double k4 = -1.5500979825922698E+02;
1661   const double k5 = 2.8184536266938172E+00;
1662   const double k6 = -2.3503421582744556E+02;
1663   const double k7 = -3.3836786704527788E+02;
1664   const double k8 = -1.3569136703258670E+02;
1665   const double k9 = 2.9914575453819188E+00;
1666   const double k10 = 1.6855569086173170E+00;
1667
1668   if (UNEXPECTED(DSD_LS624__ENABLE == 0))
1669      return;
1670
1671   /* scale due to input resistance */
1672   v_freq *= m_v_freq_scale;
1673   v_rng *= m_v_rng_scale;
1674
1675   /* apply cap if needed */
1676   if (m_has_freq_in_cap)
1677   {
1678      m_v_cap_freq_in += (v_freq - m_v_cap_freq_in) * m_exponent;
1679      v_freq = m_v_cap_freq_in;
1680   }
1681
1682   /* Polyfunctional3D_model created by zunzun.com using sum of squared absolute error */
1683   v_freq_2 = v_freq * v_freq;
1684   v_freq_3 = v_freq_2 * v_freq;
1685   v_freq_4 = v_freq_3 * v_freq;
1686   freq = k1;
1687   freq += k2 * v_freq;
1688   freq += k3 * v_freq_2;
1689   freq += k4 * v_freq_3;
1690   freq += k5 * v_freq_4;
1691   freq += k6 * v_rng;
1692   freq += k7 * v_rng * v_freq;
1693   freq += k8 * v_rng * v_freq_2;
1694   freq += k9 * v_rng * v_freq_3;
1695   freq += k10 * v_rng * v_freq_4;
1696
1697   freq *= CAP_U(0.1) / DSD_LS624__C;
1698
1699   t1 = 0.5 / freq ;
1700   t_used += this->sample_time();
1701   do
1702   {
1703      dt = 0;
1704      if (t_used > t1)
1705      {
1706         /* calculate the overshoot time */
1707         t_used -= t1;
1708         m_flip_flop ^= 1;
1709         if (m_flip_flop)
1710            count_r++;
1711         else
1712            count_f++;
1713         /* fix up any frequency increase change errors */
1714         while(t_used > this->sample_time())
1715            t_used -= this->sample_time();
1716         x_time = t_used;
1717         dt = t_used;
1718      }
1719   }while(dt);
1720
1721   m_t_used = t_used;
1722
1723   /* Convert last switch time to a ratio */
1724   x_time = x_time / this->sample_time();
1725
1726   switch (m_out_type)
1727   {
1728      case DISC_LS624_OUT_LOGIC_X:
1729         set_output(0,  m_flip_flop  + x_time);
1730         break;
1731      case DISC_LS624_OUT_COUNT_F_X:
1732         set_output(0,  count_f ? count_f + x_time : count_f);
1733         break;
1734      case DISC_LS624_OUT_COUNT_R_X:
1735         set_output(0,   count_r ? count_r + x_time : count_r);
1736         break;
1737      case DISC_LS624_OUT_COUNT_F:
1738         set_output(0,  count_f);
1739         break;
1740      case DISC_LS624_OUT_COUNT_R:
1741         set_output(0,  count_r);
1742         break;
1743      case DISC_LS624_OUT_ENERGY:
1744         if (x_time == 0) x_time = 1.0;
1745         set_output(0,  LS624_OUT_HIGH * (m_flip_flop ? x_time : (1.0 - x_time)));
1746         break;
1747      case DISC_LS624_OUT_LOGIC:
1748            set_output(0,  m_flip_flop);
1749         break;
1750      case DISC_LS624_OUT_SQUARE:
1751         set_output(0,  m_flip_flop ? LS624_OUT_HIGH : 0);
1752         break;
1753   }
1754}
1755
1756DISCRETE_RESET(dsd_ls624)
1757{
1758   m_out_type = (int)DSD_LS624__OUTTYPE;
1759
1760   m_flip_flop = 0;
1761   m_t_used = 0;
1762   m_v_freq_scale = LS624_IN_R / (DSD_LS624__R_FREQ_IN + LS624_IN_R);
1763   m_v_rng_scale = LS624_IN_R / (DSD_LS624__R_RNG_IN + LS624_IN_R);
1764   if (DSD_LS624__C_FREQ_IN > 0)
1765   {
1766      m_has_freq_in_cap = 1;
1767      m_exponent = RC_CHARGE_EXP(RES_2_PARALLEL(DSD_LS624__R_FREQ_IN, LS624_IN_R) * DSD_LS624__C_FREQ_IN);
1768      m_v_cap_freq_in = 0;
1769   }
1770   else
1771      m_has_freq_in_cap = 0;
1772
1773   set_output(0,  0);
1774}
trunk/src/emu/sound/disc_wav.c
r28731r28732
1/************************************************************************
2 *
3 *  MAME - Discrete sound system emulation library
4 *  Written by Keith Wilkins (mame@esplexo.co.uk)
5 *
6 *  (c) K.Wilkins 2000
7 *
8 ************************************************************************
9 *
10 * DSS_COUNTER        - External clock Binary Counter
11 * DSS_LFSR_NOISE     - Linear Feedback Shift Register Noise
12 * DSS_NOISE          - Noise Source - Random source
13 * DSS_NOTE           - Note/tone generator
14 * DSS_OP_AMP_OSC     - Op Amp oscillator circuits
15 * DSS_SAWTOOTHWAVE   - Sawtooth waveform generator
16 * DSS_SCHMITT_OSC    - Schmitt Feedback Oscillator
17 * DSS_SINEWAVE       - Sinewave generator source code
18 * DSS_SQUAREWAVE     - Squarewave generator source code
19 * DSS_SQUAREWFIX     - Squarewave generator - fixed frequency
20 * DSS_SQUAREWAVE2    - Squarewave generator - by t_on/t_off
21 * DSS_TRIANGLEWAVE   - Triangle waveform generator
22 *
23 ************************************************************************/
24
25
26
27
28
29
30
31/************************************************************************
32 *
33 * DSS_COUNTER - External clock Binary Counter
34 *
35 * input0    - Enable input value
36 * input1    - Reset input (active high)
37 * input2    - Clock Input
38 * input3    - Max count
39 * input4    - Direction - 0=down, 1=up
40 * input5    - Reset Value
41 * input6    - Clock type
42 *
43 * Jan 2004, D Renaud.
44 ************************************************************************/
45#define DSS_COUNTER__ENABLE     DISCRETE_INPUT(0)
46#define DSS_COUNTER__RESET      DISCRETE_INPUT(1)
47#define DSS_COUNTER__CLOCK      DISCRETE_INPUT(2)
48#define DSS_COUNTER__MIN        DISCRETE_INPUT(3)
49#define DSS_COUNTER__MAX        DISCRETE_INPUT(4)
50#define DSS_COUNTER__DIR        DISCRETE_INPUT(5)
51#define DSS_COUNTER__INIT       DISCRETE_INPUT(6)
52#define DSS_COUNTER__CLOCK_TYPE DISCRETE_INPUT(7)
53#define DSS_7492__CLOCK_TYPE     DSS_COUNTER__MIN
54
55static const int disc_7492_count[6] = {0x00, 0x01, 0x02, 0x04, 0x05, 0x06};
56
57DISCRETE_STEP(dss_counter)
58{
59   double  cycles;
60   double  ds_clock;
61   int     clock = 0, inc = 0;
62   UINT32  last_count = m_last_count;  /* it is different then output in 7492 */
63   double  x_time = 0;
64   UINT32  count = last_count;
65
66   ds_clock = DSS_COUNTER__CLOCK;
67   if (UNEXPECTED(m_clock_type == DISC_CLK_IS_FREQ))
68   {
69      /* We need to keep clocking the internal clock even if disabled. */
70      cycles = (m_t_left + this->sample_time()) * ds_clock;
71      inc    = (int)cycles;
72      m_t_left = (cycles - inc) / ds_clock;
73      if (inc) x_time = m_t_left / this->sample_time();
74   }
75   else
76   {
77      clock  = (int)ds_clock;
78      /* x_time from input clock */
79      x_time = ds_clock - clock;
80   }
81
82
83   /* If reset enabled then set output to the reset value.  No x_time in reset. */
84   if (UNEXPECTED(DSS_COUNTER__RESET))
85   {
86      m_last_count = (int)DSS_COUNTER__INIT;
87      set_output(0, (int)DSS_COUNTER__INIT);
88      return;
89   }
90
91   /*
92    * Only count if module is enabled.
93    * This has the effect of holding the output at it's current value.
94    */
95   if (EXPECTED(DSS_COUNTER__ENABLE))
96   {
97      double v_out;
98
99      switch (m_clock_type)
100      {
101         case DISC_CLK_ON_F_EDGE:
102         case DISC_CLK_ON_R_EDGE:
103            /* See if the clock has toggled to the proper edge */
104            clock = (clock != 0);
105            if (m_last_clock != clock)
106            {
107               m_last_clock = clock;
108               if (m_clock_type == clock)
109               {
110                  /* Toggled */
111                  inc = 1;
112               }
113            }
114            break;
115
116         case DISC_CLK_BY_COUNT:
117            /* Clock number of times specified. */
118            inc = clock;
119            break;
120      }
121
122      /* use loops because init is not always min or max */
123      if (DSS_COUNTER__DIR)
124      {
125         count += inc;
126         while (count > m_max)
127         {
128            count -= m_diff;
129         }
130      }
131      else
132      {
133         count -= inc;
134         while (count < m_min || count > (0xffffffff - inc))
135         {
136            count += m_diff;
137         }
138      }
139
140      m_last_count = count;
141      v_out = m_is_7492 ? disc_7492_count[count] : count;
142
143      if (UNEXPECTED(count != last_count))
144      {
145         /* the x_time is only output if the output changed. */
146         switch (m_out_type)
147         {
148            case DISC_OUT_HAS_XTIME:
149               v_out += x_time;
150               break;
151            case DISC_OUT_IS_ENERGY:
152               if (x_time == 0) x_time = 1.0;
153               v_out = last_count;
154               if (count > last_count)
155                  v_out += (count - last_count) * x_time;
156               else
157                  v_out -= (last_count - count) * x_time;
158               break;
159         }
160      }
161      set_output(0, v_out);
162   }
163}
164
165DISCRETE_RESET(dss_counter)
166{
167   if ((int)DSS_COUNTER__CLOCK_TYPE & DISC_COUNTER_IS_7492)
168   {
169      m_is_7492    = 1;
170      m_clock_type = DSS_7492__CLOCK_TYPE;
171      m_max = 5;
172      m_min = 0;
173      m_diff = 6;
174   }
175   else
176   {
177      m_is_7492    = 0;
178      m_clock_type = DSS_COUNTER__CLOCK_TYPE;
179      m_max = DSS_COUNTER__MAX;
180      m_min = DSS_COUNTER__MIN;
181      m_diff = m_max - m_min + 1;
182   }
183
184
185   if (!m_is_7492 && (DSS_COUNTER__MAX < DSS_COUNTER__MIN))
186      fatalerror("MAX < MIN in NODE_%02d\n", this->index());
187
188   m_out_type    = m_clock_type & DISC_OUT_MASK;
189   m_clock_type &= DISC_CLK_MASK;
190
191   m_t_left = 0;
192   m_last_count = 0;
193   m_last_clock = 0;
194   set_output(0, DSS_COUNTER__INIT); /* count starts at reset value */
195}
196
197
198/************************************************************************
199 *
200 * DSS_LFSR_NOISE - Usage of node_description values for LFSR noise gen
201 *
202 * input0    - Enable input value
203 * input1    - Register reset
204 * input2    - Clock Input
205 * input3    - Amplitude input value
206 * input4    - Input feed bit
207 * input5    - Bias
208 *
209 * also passed dss_lfsr_context structure
210 *
211 ************************************************************************/
212#define DSS_LFSR_NOISE__ENABLE  DISCRETE_INPUT(0)
213#define DSS_LFSR_NOISE__RESET   DISCRETE_INPUT(1)
214#define DSS_LFSR_NOISE__CLOCK   DISCRETE_INPUT(2)
215#define DSS_LFSR_NOISE__AMP     DISCRETE_INPUT(3)
216#define DSS_LFSR_NOISE__FEED    DISCRETE_INPUT(4)
217#define DSS_LFSR_NOISE__BIAS    DISCRETE_INPUT(5)
218
219INLINE int dss_lfsr_function(discrete_device *dev, int myfunc, int in0, int in1, int bitmask)
220{
221   int retval;
222
223   in0 &= bitmask;
224   in1 &= bitmask;
225
226   switch(myfunc)
227   {
228      case DISC_LFSR_XOR:
229         retval = in0 ^ in1;
230         break;
231      case DISC_LFSR_OR:
232         retval = in0 | in1;
233         break;
234      case DISC_LFSR_AND:
235         retval = in0 & in1;
236         break;
237      case DISC_LFSR_XNOR:
238         retval = in0 ^ in1;
239         retval = retval ^ bitmask;  /* Invert output */
240         break;
241      case DISC_LFSR_NOR:
242         retval = in0 | in1;
243         retval = retval ^ bitmask;  /* Invert output */
244         break;
245      case DISC_LFSR_NAND:
246         retval = in0 & in1;
247         retval = retval ^ bitmask;  /* Invert output */
248         break;
249      case DISC_LFSR_IN0:
250         retval = in0;
251         break;
252      case DISC_LFSR_IN1:
253         retval = in1;
254         break;
255      case DISC_LFSR_NOT_IN0:
256         retval = in0 ^ bitmask;
257         break;
258      case DISC_LFSR_NOT_IN1:
259         retval = in1 ^ bitmask;
260         break;
261      case DISC_LFSR_REPLACE:
262         retval = in0 & ~in1;
263         retval = retval | in1;
264         break;
265      case DISC_LFSR_XOR_INV_IN0:
266         retval = in0 ^ bitmask; /* invert in0 */
267         retval = retval ^ in1;  /* xor in1 */
268         break;
269      case DISC_LFSR_XOR_INV_IN1:
270         retval = in1 ^ bitmask; /* invert in1 */
271         retval = retval ^ in0;  /* xor in0 */
272         break;
273      default:
274         dev->discrete_log("dss_lfsr_function - Invalid function type passed");
275         retval=0;
276         break;
277   }
278   return retval;
279}
280
281
282DISCRETE_STEP(dss_lfsr_noise)
283{
284   DISCRETE_DECLARE_INFO(discrete_lfsr_desc)
285
286   double cycles;
287   int clock, inc = 0;
288   int fb0, fb1, fbresult = 0, noise_feed;
289
290   if (info->clock_type == DISC_CLK_IS_FREQ)
291   {
292      /* We need to keep clocking the internal clock even if disabled. */
293      cycles = (m_t_left + this->sample_time()) / m_t_clock;
294      inc    = (int)cycles;
295      m_t_left = (cycles - inc) * m_t_clock;
296   }
297
298   /* Reset everything if necessary */
299   if(((DSS_LFSR_NOISE__RESET == 0) ? 0 : 1) == m_reset_on_high)
300   {
301      this->reset();
302      return;
303   }
304
305   switch (info->clock_type)
306   {
307      case DISC_CLK_ON_F_EDGE:
308      case DISC_CLK_ON_R_EDGE:
309         /* See if the clock has toggled to the proper edge */
310         clock = (DSS_LFSR_NOISE__CLOCK != 0);
311         if (m_last != clock)
312         {
313            m_last = clock;
314            if (info->clock_type == clock)
315            {
316               /* Toggled */
317               inc = 1;
318            }
319         }
320         break;
321
322      case DISC_CLK_BY_COUNT:
323         /* Clock number of times specified. */
324         inc = (int)DSS_LFSR_NOISE__CLOCK;
325         break;
326   }
327
328   if (inc > 0)
329   {
330      double v_out;
331
332      noise_feed = (DSS_LFSR_NOISE__FEED ? 0x01 : 0x00);
333      for (clock = 0; clock < inc; clock++)
334      {
335         /* Fetch the last feedback result */
336         fbresult = (m_lfsr_reg >> info->bitlength) & 0x01;
337
338         /* Stage 2 feedback combine fbresultNew with infeed bit */
339         fbresult = dss_lfsr_function(m_device, info->feedback_function1, fbresult, noise_feed, 0x01);
340
341         /* Stage 3 first we setup where the bit is going to be shifted into */
342         fbresult = fbresult * info->feedback_function2_mask;
343         /* Then we left shift the register, */
344         m_lfsr_reg = m_lfsr_reg << 1;
345         /* Now move the fbresult into the shift register and mask it to the bitlength */
346         m_lfsr_reg = dss_lfsr_function(m_device, info->feedback_function2, fbresult, m_lfsr_reg, (1 << info->bitlength) - 1 );
347
348         /* Now get and store the new feedback result */
349         /* Fetch the feedback bits */
350         fb0 = (m_lfsr_reg >> info->feedback_bitsel0) & 0x01;
351         fb1 = (m_lfsr_reg >> info->feedback_bitsel1) & 0x01;
352         /* Now do the combo on them */
353         fbresult = dss_lfsr_function(m_device, info->feedback_function0, fb0, fb1, 0x01);
354         m_lfsr_reg = dss_lfsr_function(m_device, DISC_LFSR_REPLACE, m_lfsr_reg, fbresult << info->bitlength, (2 << info->bitlength) - 1);
355
356      }
357      /* Now select the output bit */
358      if (m_out_is_f0)
359         v_out = fbresult & 0x01;
360      else
361         v_out = (m_lfsr_reg >> info->output_bit) & 0x01;
362
363      /* Final inversion if required */
364      if (m_invert_output) v_out = v_out ? 0 : 1;
365
366      /* Gain stage */
367      v_out = v_out ? DSS_LFSR_NOISE__AMP / 2 : -DSS_LFSR_NOISE__AMP / 2;
368      /* Bias input as required */
369      v_out = v_out + DSS_LFSR_NOISE__BIAS;
370
371      set_output(0, v_out);
372
373      /* output the lfsr reg ?*/
374      if (m_out_lfsr_reg)
375         set_output(1, (double) m_lfsr_reg);
376
377   }
378   if(!DSS_LFSR_NOISE__ENABLE)
379   {
380      set_output(0, 0);
381   }
382}
383
384DISCRETE_RESET(dss_lfsr_noise)
385{
386   DISCRETE_DECLARE_INFO(discrete_lfsr_desc)
387
388   int    fb0 , fb1, fbresult;
389   double v_out;
390
391   m_reset_on_high = (info->flags & DISC_LFSR_FLAG_RESET_TYPE_H) ? 1 : 0;
392   m_invert_output = info->flags & DISC_LFSR_FLAG_OUT_INVERT;
393   m_out_is_f0 = (info->flags & DISC_LFSR_FLAG_OUTPUT_F0) ? 1 : 0;
394   m_out_lfsr_reg = (info->flags & DISC_LFSR_FLAG_OUTPUT_SR_SN1) ? 1 : 0;
395
396   if ((info->clock_type < DISC_CLK_ON_F_EDGE) || (info->clock_type > DISC_CLK_IS_FREQ))
397      m_device->discrete_log("Invalid clock type passed in NODE_%d\n", this->index());
398
399   m_last = (DSS_COUNTER__CLOCK != 0);
400   if (info->clock_type == DISC_CLK_IS_FREQ) m_t_clock = 1.0 / DSS_LFSR_NOISE__CLOCK;
401   m_t_left = 0;
402
403   m_lfsr_reg = info->reset_value;
404
405   /* Now get and store the new feedback result */
406   /* Fetch the feedback bits */
407   fb0 = (m_lfsr_reg >> info->feedback_bitsel0) & 0x01;
408   fb1=(m_lfsr_reg >> info->feedback_bitsel1) & 0x01;
409   /* Now do the combo on them */
410   fbresult = dss_lfsr_function(m_device, info->feedback_function0, fb0, fb1, 0x01);
411   m_lfsr_reg=dss_lfsr_function(m_device, DISC_LFSR_REPLACE, m_lfsr_reg, fbresult << info->bitlength, (2<< info->bitlength ) - 1);
412
413   /* Now select and setup the output bit */
414   v_out = (m_lfsr_reg >> info->output_bit) & 0x01;
415
416   /* Final inversion if required */
417   if(info->flags & DISC_LFSR_FLAG_OUT_INVERT) v_out = v_out ? 0 : 1;
418
419   /* Gain stage */
420   v_out = v_out ? DSS_LFSR_NOISE__AMP / 2 : -DSS_LFSR_NOISE__AMP / 2;
421   /* Bias input as required */
422   v_out += DSS_LFSR_NOISE__BIAS;
423
424   set_output(0, v_out);
425   set_output(1, 0);
426}
427
428
429/************************************************************************
430 *
431 * DSS_NOISE - Usage of node_description values for white nose generator
432 *
433 * input0    - Enable input value
434 * input1    - Noise sample frequency
435 * input2    - Amplitude input value
436 * input3    - DC Bias value
437 *
438 ************************************************************************/
439#define DSS_NOISE__ENABLE   DISCRETE_INPUT(0)
440#define DSS_NOISE__FREQ     DISCRETE_INPUT(1)
441#define DSS_NOISE__AMP      DISCRETE_INPUT(2)
442#define DSS_NOISE__BIAS     DISCRETE_INPUT(3)
443
444DISCRETE_STEP(dss_noise)
445{
446   double v_out;
447
448   if(DSS_NOISE__ENABLE)
449   {
450      /* Only sample noise on rollover to next cycle */
451      if(m_phase > (2.0 * M_PI))
452      {
453         /* GCC's rand returns a RAND_MAX value of 0x7fff */
454         int newval = (m_device->machine().rand() & 0x7fff) - 16384;
455
456         /* make sure the peak to peak values are the amplitude */
457         v_out = DSS_NOISE__AMP / 2;
458         if (newval > 0)
459            v_out *= ((double)newval / 16383);
460         else
461            v_out *= ((double)newval / 16384);
462
463         /* Add DC Bias component */
464         v_out += DSS_NOISE__BIAS;
465         set_output(0, v_out);
466      }
467   }
468   else
469   {
470      set_output(0, 0);
471   }
472
473   /* Keep the new phasor in the 2Pi range.*/
474   m_phase = fmod(m_phase, 2.0 * M_PI);
475
476   /* The enable input only curtails output, phase rotation still occurs. */
477   /* We allow the phase to exceed 2Pi here, so we can tell when to sample the noise. */
478   m_phase += ((2.0 * M_PI * DSS_NOISE__FREQ) / this->sample_rate());
479}
480
481
482DISCRETE_RESET(dss_noise)
483{
484   m_phase=0;
485   this->step();
486}
487
488
489/************************************************************************
490 *
491 * DSS_NOTE - Note/tone generator
492 *
493 * input0    - Enable input value
494 * input1    - Clock Input
495 * input2    - data value
496 * input3    - Max count 1
497 * input4    - Max count 2
498 * input5    - Clock type
499 *
500 * Mar 2004, D Renaud.
501 ************************************************************************/
502   #define DSS_NOTE__ENABLE        DISCRETE_INPUT(0)
503   #define DSS_NOTE__CLOCK     DISCRETE_INPUT(1)
504   #define DSS_NOTE__DATA          DISCRETE_INPUT(2)
505   #define DSS_NOTE__MAX1          DISCRETE_INPUT(3)
506   #define DSS_NOTE__MAX2          DISCRETE_INPUT(4)
507   #define DSS_NOTE__CLOCK_TYPE    DISCRETE_INPUT(5)
508
509DISCRETE_STEP(dss_note)
510{
511   double  cycles;
512   int     clock  = 0, last_count2, inc = 0;
513   double  x_time = 0;
514   double  v_out;
515
516   if (m_clock_type == DISC_CLK_IS_FREQ)
517   {
518      /* We need to keep clocking the internal clock even if disabled. */
519      cycles = (m_t_left + this->sample_time()) / m_t_clock;
520      inc    = (int)cycles;
521      m_t_left = (cycles - inc) * m_t_clock;
522      if (inc) x_time = m_t_left / this->sample_time();
523   }
524   else
525   {
526      /* separate clock info from x_time info. */
527      clock = (int)DSS_NOTE__CLOCK;
528      x_time = DSS_NOTE__CLOCK - clock;
529   }
530
531   if (DSS_NOTE__ENABLE)
532   {
533      last_count2 = m_count2;
534
535      switch (m_clock_type)
536      {
537         case DISC_CLK_ON_F_EDGE:
538         case DISC_CLK_ON_R_EDGE:
539            /* See if the clock has toggled to the proper edge */
540            clock = (clock != 0);
541            if (m_last != clock)
542            {
543               m_last = clock;
544               if (m_clock_type == clock)
545               {
546                  /* Toggled */
547                  inc = 1;
548               }
549            }
550            break;
551
552         case DISC_CLK_BY_COUNT:
553            /* Clock number of times specified. */
554            inc = clock;
555            break;
556      }
557
558      /* Count output as long as the data loaded is not already equal to max 1 count. */
559      if (DSS_NOTE__DATA != DSS_NOTE__MAX1)
560      {
561         for (clock = 0; clock < inc; clock++)
562         {
563            m_count1++;
564            if (m_count1 > m_max1)
565            {
566               /* Max 1 count reached.  Load Data into counter. */
567               m_count1  = (int)DSS_NOTE__DATA;
568               m_count2 += 1;
569               if (m_count2 > m_max2) m_count2 = 0;
570            }
571         }
572      }
573
574      v_out = m_count2;
575      if (m_count2 != last_count2)
576      {
577         /* the x_time is only output if the output changed. */
578         switch (m_out_type)
579         {
580            case DISC_OUT_IS_ENERGY:
581               if (x_time == 0) x_time = 1.0;
582               v_out = last_count2;
583               if (m_count2 > last_count2)
584                  v_out += (m_count2 - last_count2) * x_time;
585               else
586                  v_out -= (last_count2 - m_count2) * x_time;
587               break;
588            case DISC_OUT_HAS_XTIME:
589               v_out += x_time;
590               break;
591         }
592      }
593      set_output(0, v_out);
594   }
595   else
596      set_output(0, 0);
597}
598
599DISCRETE_RESET(dss_note)
600{
601   m_clock_type = (int)DSS_NOTE__CLOCK_TYPE & DISC_CLK_MASK;
602   m_out_type   = (int)DSS_NOTE__CLOCK_TYPE & DISC_OUT_MASK;
603
604   m_last    = (DSS_NOTE__CLOCK != 0);
605   m_t_left  = 0;
606   m_t_clock = 1.0 / DSS_NOTE__CLOCK;
607
608   m_count1 = (int)DSS_NOTE__DATA;
609   m_count2 = 0;
610   m_max1   = (int)DSS_NOTE__MAX1;
611   m_max2   = (int)DSS_NOTE__MAX2;
612   set_output(0, 0);
613}
614
615/************************************************************************
616 *
617 * DSS_OP_AMP_OSC - Op Amp Oscillators
618 *
619 * input0    - Enable input value
620 * input1    - vMod1 (if needed)
621 * input2    - vMod2 (if needed)
622 *
623 * also passed discrete_op_amp_osc_info structure
624 *
625 * Mar 2004, D Renaud.
626 ************************************************************************/
627#define DSS_OP_AMP_OSC__ENABLE  DISCRETE_INPUT(0)
628#define DSS_OP_AMP_OSC__VMOD1   DISCRETE_INPUT(1)
629#define DSS_OP_AMP_OSC__VMOD2   DISCRETE_INPUT(2)
630
631/* The inputs on a norton op-amp are (info->vP - OP_AMP_NORTON_VBE) */
632/* which is the same as the output high voltage.  We will define them */
633/* the same to save a calculation step */
634#define DSS_OP_AMP_OSC_NORTON_VP_IN     m_v_out_high
635
636DISCRETE_STEP(dss_op_amp_osc)
637{
638   DISCRETE_DECLARE_INFO(discrete_op_amp_osc_info)
639
640   double i = 0;               /* Charging current created by vIn */
641   double v = 0;           /* all input voltages mixed */
642   double dt;              /* change in time */
643   double v_cap;           /* Current voltage on capacitor, before dt */
644   double v_cap_next = 0;  /* Voltage on capacitor, after dt */
645   double charge[2]  = {0};
646   double x_time  = 0;     /* time since change happened */
647   double exponent;
648   UINT8 force_charge = 0;
649   UINT8 enable = DSS_OP_AMP_OSC__ENABLE;
650   UINT8 update_exponent = 0;
651   UINT8 flip_flop = m_flip_flop;
652   int count_f = 0;
653   int count_r = 0;
654
655   double v_out = 0;
656
657   dt = this->sample_time();   /* Change in time */
658   v_cap = m_v_cap;    /* Set to voltage before change */
659
660   /* work out the charge currents/voltages. */
661   switch (m_type)
662   {
663      case DISC_OP_AMP_OSCILLATOR_VCO_1:
664         /* Work out the charge rates. */
665         /* i is not a current.  It is being used as a temp variable. */
666         i = DSS_OP_AMP_OSC__VMOD1 * m_temp1;
667         charge[0] = (DSS_OP_AMP_OSC__VMOD1 - i) / info->r1;
668         charge[1] = (i - (DSS_OP_AMP_OSC__VMOD1 * m_temp2)) / m_temp3;
669         break;
670
671      case DISC_OP_AMP_OSCILLATOR_1 | DISC_OP_AMP_IS_NORTON:
672      {
673         /* resistors can be nodes, so everything needs updating */
674         double i1, i2;
675         /* add in enable current if using real enable */
676         if (m_has_enable)
677         {
678            if (enable)
679               i = m_i_enable;
680            enable = 1;
681         }
682         /* Work out the charge rates. */
683         charge[0] = DSS_OP_AMP_OSC_NORTON_VP_IN / *m_r[1-1] - i;
684         charge[1] = (m_v_out_high - OP_AMP_NORTON_VBE) / *m_r[2-1] - charge[0];
685         /* Work out the Inverting Schmitt thresholds. */
686         i1 = DSS_OP_AMP_OSC_NORTON_VP_IN / *m_r[5-1];
687         i2 = (0.0 - OP_AMP_NORTON_VBE) / *m_r[4-1];
688         m_threshold_low  = (i1 + i2) * *m_r[3-1] + OP_AMP_NORTON_VBE;
689         i2 = (m_v_out_high - OP_AMP_NORTON_VBE) / *m_r[4-1];
690         m_threshold_high = (i1 + i2) * *m_r[3-1] + OP_AMP_NORTON_VBE;
691         break;
692      }
693
694      case DISC_OP_AMP_OSCILLATOR_VCO_1 | DISC_OP_AMP_IS_NORTON:
695         /* Millman the input voltages. */
696         if (info->r7 == 0)
697         {
698            /* No r7 means that the modulation circuit is fed directly into the circuit. */
699            v = DSS_OP_AMP_OSC__VMOD1;
700         }
701         else
702         {
703            /* we need to mix any bias and all modulation voltages together. */
704            i  = m_i_fixed;
705            i += DSS_OP_AMP_OSC__VMOD1 / info->r7;
706            if (info->r8 != 0)
707               i += DSS_OP_AMP_OSC__VMOD2 / info->r8;
708            v  = i * m_r_total;
709         }
710
711         /* Work out the charge rates. */
712         v -= OP_AMP_NORTON_VBE;
713         charge[0] = v / info->r1;
714         charge[1] = v / info->r2 - charge[0];
715
716         /* use the real enable circuit */
717         force_charge = !enable;
718         enable = 1;
719         break;
720
721      case DISC_OP_AMP_OSCILLATOR_VCO_2 | DISC_OP_AMP_IS_NORTON:
722         /* Work out the charge rates. */
723         i = DSS_OP_AMP_OSC__VMOD1 / info->r1;
724         charge[0] = i - m_temp1;
725         charge[1] = m_temp2 - i;
726         /* if the negative pin current is less then the positive pin current, */
727         /* then the osc is disabled and the cap keeps charging */
728         if (charge[0] < 0)
729         {
730            force_charge =  1;
731            charge[0]  *= -1;
732         }
733         break;
734
735      case DISC_OP_AMP_OSCILLATOR_VCO_3 | DISC_OP_AMP_IS_NORTON:
736         /* start with fixed bias */
737         charge[0] = m_i_fixed;
738         /* add in enable current if using real enable */
739         if (m_has_enable)
740         {
741            if (enable)
742               charge[0] -= m_i_enable;
743            enable = 1;
744         }
745         /* we need to mix any bias and all modulation voltages together. */
746         v = DSS_OP_AMP_OSC__VMOD1 - OP_AMP_NORTON_VBE;
747         if (v < 0) v = 0;
748         charge[0] += v / info->r1;
749         if (info->r6 != 0)
750         {
751            v = DSS_OP_AMP_OSC__VMOD2 - OP_AMP_NORTON_VBE;
752            charge[0] += v / info->r6;
753         }
754         charge[1] = m_temp1 - charge[0];
755         break;
756   }
757
758   if (!enable)
759   {
760      /* we will just output 0 for oscillators that have no real enable. */
761      set_output(0, 0);
762      return;
763   }
764
765   /* Keep looping until all toggling in time sample is used up. */
766   do
767   {
768      if (m_is_linear_charge)
769      {
770         if ((flip_flop ^ m_flip_flop_xor) || force_charge)
771         {
772            /* Charging */
773            /* iC=C*dv/dt  works out to dv=iC*dt/C */
774            v_cap_next = v_cap + (charge[1] * dt / info->c);
775            dt = 0;
776
777            /* has it charged past upper limit? */
778            if (v_cap_next > m_threshold_high)
779            {
780               flip_flop = m_flip_flop_xor;
781               if (flip_flop)
782                  count_r++;
783               else
784                  count_f++;
785               if (force_charge)
786               {
787                  /* we need to keep charging the cap to the max thereby disabling the circuit */
788                  if (v_cap_next > m_v_out_high)
789                     v_cap_next = m_v_out_high;
790               }
791               else
792               {
793                  /* calculate the overshoot time */
794                  dt = info->c * (v_cap_next - m_threshold_high) / charge[1];
795                  x_time = dt;
796                  v_cap_next = m_threshold_high;
797               }
798            }
799         }
800         else
801         {
802            /* Discharging */
803            v_cap_next = v_cap - (charge[0] * dt / info->c);
804            dt     = 0;
805
806            /* has it discharged past lower limit? */
807            if (v_cap_next < m_threshold_low)
808            {
809               flip_flop = !m_flip_flop_xor;
810               if (flip_flop)
811                  count_r++;
812               else
813                  count_f++;
814               /* calculate the overshoot time */
815               dt = info->c * (m_threshold_low - v_cap_next) / charge[0];
816               x_time = dt;
817               v_cap_next = m_threshold_low;
818            }
819         }
820      }
821      else    /* non-linear charge */
822      {
823         if (update_exponent)
824            exponent = RC_CHARGE_EXP_DT(m_charge_rc[flip_flop], dt);
825         else
826            exponent = m_charge_exp[flip_flop];
827
828         v_cap_next = v_cap + ((m_charge_v[flip_flop] - v_cap) * exponent);
829         dt = 0;
830
831         if (flip_flop)
832         {
833            /* Has it charged past upper limit? */
834            if (v_cap_next > m_threshold_high)
835            {
836               dt = m_charge_rc[1]  * log(1.0 / (1.0 - ((v_cap_next - m_threshold_high) / (m_v_out_high - v_cap))));
837               x_time = dt;
838               v_cap_next = m_threshold_high;
839               flip_flop = 0;
840               count_f++;
841               update_exponent = 1;
842            }
843         }
844         else
845         {
846            /* has it discharged past lower limit? */
847            if (v_cap_next < m_threshold_low)
848            {
849               dt = m_charge_rc[0] * log(1.0 / (1.0 - ((m_threshold_low - v_cap_next) / v_cap)));
850               x_time = dt;
851               v_cap_next = m_threshold_low;
852               flip_flop = 1;
853               count_r++;
854               update_exponent = 1;
855            }
856         }
857      }
858      v_cap = v_cap_next;
859   } while(dt);
860   if (v_cap > m_v_out_high)
861      v_cap = m_v_out_high;
862   if (v_cap < 0)
863      v_cap = 0;
864   m_v_cap = v_cap;
865
866   x_time = dt / this->sample_time();
867
868   switch (m_output_type)
869   {
870      case DISC_OP_AMP_OSCILLATOR_OUT_CAP:
871         v_out = v_cap;
872         break;
873      case DISC_OP_AMP_OSCILLATOR_OUT_ENERGY:
874         if (x_time == 0) x_time = 1.0;
875         v_out = m_v_out_high * (flip_flop ? x_time : (1.0 - x_time));
876         break;
877      case DISC_OP_AMP_OSCILLATOR_OUT_SQW:
878         if (count_f + count_r >= 2)
879            /* force at least 1 toggle */
880            v_out = m_flip_flop ? 0 : m_v_out_high;
881         else
882            v_out = flip_flop * m_v_out_high;
883         break;
884      case DISC_OP_AMP_OSCILLATOR_OUT_COUNT_F_X:
885         v_out = count_f ? count_f + x_time : count_f;
886         break;
887      case DISC_OP_AMP_OSCILLATOR_OUT_COUNT_R_X:
888         v_out =  count_r ? count_r + x_time : count_r;
889         break;
890      case DISC_OP_AMP_OSCILLATOR_OUT_LOGIC_X:
891         v_out = m_flip_flop + x_time;
892         break;
893   }
894   set_output(0, v_out);
895   m_flip_flop = flip_flop;
896}
897
898#define DIODE_DROP  0.7
899
900DISCRETE_RESET(dss_op_amp_osc)
901{
902   DISCRETE_DECLARE_INFO(discrete_op_amp_osc_info)
903
904   const double *r_info_ptr;
905   int loop;
906
907   double i1 = 0;  /* inverting input current */
908   double i2 = 0;  /* non-inverting input current */
909
910   /* link to resistor static or node values */
911   r_info_ptr    = &info->r1;
912   for (loop = 0; loop < 8; loop ++)
913   {
914      m_r[loop] = m_device->node_output_ptr(*r_info_ptr);
915      if (m_r[loop] == NULL)
916         m_r[loop] = r_info_ptr;
917      r_info_ptr++;
918   }
919
920   m_is_linear_charge = 1;
921   m_output_type = info->type & DISC_OP_AMP_OSCILLATOR_OUT_MASK;
922   m_type        = info->type & DISC_OP_AMP_OSCILLATOR_TYPE_MASK;
923   m_charge_rc[0] = 0;
924   m_charge_rc[1] = 0;
925   m_charge_v[0] = 0;
926   m_charge_v[1] = 0;
927   m_i_fixed = 0;
928   m_has_enable = 0;
929
930   switch (m_type)
931   {
932      case DISC_OP_AMP_OSCILLATOR_VCO_1:
933         /* The charge rates vary depending on vMod so they are not precalculated. */
934         /* Charges while FlipFlop High */
935         m_flip_flop_xor = 0;
936         /* Work out the Non-inverting Schmitt thresholds. */
937         m_temp1 = (info->vP / 2) / info->r4;
938         m_temp2 = (info->vP - OP_AMP_VP_RAIL_OFFSET) / info->r3;
939         m_temp3 = 1.0 / (1.0 / info->r3 + 1.0 / info->r4);
940         m_threshold_low  =  m_temp1 * m_temp3;
941         m_threshold_high = (m_temp1 + m_temp2) * m_temp3;
942         /* There is no charge on the cap so the schmitt goes high at init. */
943         m_flip_flop = 1;
944         /* Setup some commonly used stuff */
945         m_temp1 = info->r5 / (info->r2 + info->r5);         /* voltage ratio across r5 */
946         m_temp2 = info->r6 / (info->r1 + info->r6);         /* voltage ratio across r6 */
947         m_temp3 = 1.0 / (1.0 / info->r1 + 1.0 / info->r6);  /* input resistance when r6 switched in */
948         break;
949
950      case DISC_OP_AMP_OSCILLATOR_1 | DISC_OP_AMP_IS_NORTON:
951         /* Charges while FlipFlop High */
952         m_flip_flop_xor = 0;
953         /* There is no charge on the cap so the schmitt inverter goes high at init. */
954         m_flip_flop = 1;
955         /* setup current if using real enable */
956         if (info->r6 > 0)
957         {
958            m_has_enable = 1;
959            m_i_enable = (info->vP - OP_AMP_NORTON_VBE) / (info->r6 + RES_K(1));
960         }
961         break;
962
963      case DISC_OP_AMP_OSCILLATOR_2 | DISC_OP_AMP_IS_NORTON:
964         m_is_linear_charge = 0;
965         /* First calculate the parallel charge resistors and volatges. */
966         /* We can cheat and just calcuate the charges in the working area. */
967         /* The thresholds are well past the effect of the voltage drop */
968         /* and the component tolerances far exceed the .5V charge difference */
969         if (info->r1 != 0)
970         {
971            m_charge_rc[0] = 1.0 / info->r1;
972            m_charge_rc[1] = 1.0 / info->r1;
973            m_charge_v[1] = (info->vP - OP_AMP_NORTON_VBE) / info->r1;
974         }
975         if (info->r5 != 0)
976         {
977            m_charge_rc[0] += 1.0 / info->r5;
978            m_charge_v[0] = DIODE_DROP / info->r5;
979         }
980         if (info->r6 != 0)
981         {
982            m_charge_rc[1] += 1.0 / info->r6;
983            m_charge_v[1] += (info->vP - OP_AMP_NORTON_VBE - DIODE_DROP) / info->r6;
984         }
985         m_charge_rc[0] += 1.0 / info->r2;
986         m_charge_rc[0] = 1.0 / m_charge_rc[0];
987         m_charge_v[0] += OP_AMP_NORTON_VBE / info->r2;
988         m_charge_v[0] *= m_charge_rc[0];
989         m_charge_rc[1] += 1.0 / info->r2;
990         m_charge_rc[1] = 1.0 / m_charge_rc[1];
991         m_charge_v[1] += OP_AMP_NORTON_VBE / info->r2;
992         m_charge_v[1] *= m_charge_rc[1];
993
994         m_charge_rc[0] *= info->c;
995         m_charge_rc[1] *= info->c;
996         m_charge_exp[0] = RC_CHARGE_EXP(m_charge_rc[0]);
997         m_charge_exp[1] = RC_CHARGE_EXP(m_charge_rc[1]);
998         m_threshold_low  = (info->vP - OP_AMP_NORTON_VBE) / info->r4;
999         m_threshold_high = m_threshold_low + (info->vP - 2 * OP_AMP_NORTON_VBE) / info->r3;;
1000         m_threshold_low  = m_threshold_low * info->r2 + OP_AMP_NORTON_VBE;
1001         m_threshold_high = m_threshold_high * info->r2 + OP_AMP_NORTON_VBE;
1002
1003         /* There is no charge on the cap so the schmitt inverter goes high at init. */
1004         m_flip_flop = 1;
1005         break;
1006
1007      case DISC_OP_AMP_OSCILLATOR_VCO_1 | DISC_OP_AMP_IS_NORTON:
1008         /* Charges while FlipFlop Low */
1009         m_flip_flop_xor = 1;
1010         /* There is no charge on the cap so the schmitt goes low at init. */
1011         m_flip_flop = 0;
1012         /* The charge rates vary depending on vMod so they are not precalculated. */
1013         /* But we can precalculate the fixed currents. */
1014         if (info->r6 != 0) m_i_fixed += info->vP / info->r6;
1015         m_i_fixed += OP_AMP_NORTON_VBE / info->r1;
1016         m_i_fixed += OP_AMP_NORTON_VBE / info->r2;
1017         /* Work out the input resistance to be used later to calculate the Millman voltage. */
1018         m_r_total = 1.0 / info->r1 + 1.0 / info->r2 + 1.0 / info->r7;
1019         if (info->r6) m_r_total += 1.0 / info->r6;
1020         if (info->r8) m_r_total += 1.0 / info->r8;
1021         m_r_total = 1.0 / m_r_total;
1022         /* Work out the Non-inverting Schmitt thresholds. */
1023         i1 = (info->vP - OP_AMP_NORTON_VBE) / info->r5;
1024         i2 = (info->vP - OP_AMP_NORTON_VBE - OP_AMP_NORTON_VBE) / info->r4;
1025         m_threshold_low = (i1 - i2) * info->r3 + OP_AMP_NORTON_VBE;
1026         i2 = (0.0 - OP_AMP_NORTON_VBE) / info->r4;
1027         m_threshold_high = (i1 - i2) * info->r3 + OP_AMP_NORTON_VBE;
1028         break;
1029
1030      case DISC_OP_AMP_OSCILLATOR_VCO_2 | DISC_OP_AMP_IS_NORTON:
1031         /* Charges while FlipFlop High */
1032         m_flip_flop_xor = 0;
1033         /* There is no charge on the cap so the schmitt inverter goes high at init. */
1034         m_flip_flop = 1;
1035         /* Work out the charge rates. */
1036         m_temp1 = (info->vP - OP_AMP_NORTON_VBE) / info->r2;
1037         m_temp2 = (info->vP - OP_AMP_NORTON_VBE) * (1.0 / info->r2 + 1.0 / info->r6);
1038         /* Work out the Inverting Schmitt thresholds. */
1039         i1 = (info->vP - OP_AMP_NORTON_VBE) / info->r5;
1040         i2 = (0.0 - OP_AMP_NORTON_VBE) / info->r4;
1041         m_threshold_low = (i1 + i2) * info->r3 + OP_AMP_NORTON_VBE;
1042         i2 = (info->vP - OP_AMP_NORTON_VBE - OP_AMP_NORTON_VBE) / info->r4;
1043         m_threshold_high = (i1 + i2) * info->r3 + OP_AMP_NORTON_VBE;
1044         break;
1045
1046      case DISC_OP_AMP_OSCILLATOR_VCO_3 | DISC_OP_AMP_IS_NORTON:
1047         /* Charges while FlipFlop High */
1048         m_flip_flop_xor = 0;
1049         /* There is no charge on the cap so the schmitt inverter goes high at init. */
1050         m_flip_flop = 1;
1051         /* setup current if using real enable */
1052         if (info->r8 > 0)
1053         {
1054            m_has_enable = 1;
1055            m_i_enable = (info->vP - OP_AMP_NORTON_VBE) / (info->r8 + RES_K(1));
1056         }
1057         /* Work out the charge rates. */
1058         /* The charge rates vary depending on vMod so they are not precalculated. */
1059         /* But we can precalculate the fixed currents. */
1060         if (info->r7 != 0) m_i_fixed = (info->vP - OP_AMP_NORTON_VBE) / info->r7;
1061         m_temp1 = (info->vP - OP_AMP_NORTON_VBE - OP_AMP_NORTON_VBE) / info->r2;
1062         /* Work out the Inverting Schmitt thresholds. */
1063         i1 = (info->vP - OP_AMP_NORTON_VBE) / info->r5;
1064         i2 = (0.0 - OP_AMP_NORTON_VBE) / info->r4;
1065         m_threshold_low = (i1 + i2) * info->r3 + OP_AMP_NORTON_VBE;
1066         i2 = (info->vP - OP_AMP_NORTON_VBE - OP_AMP_NORTON_VBE) / info->r4;
1067         m_threshold_high = (i1 + i2) * info->r3 + OP_AMP_NORTON_VBE;
1068         break;
1069   }
1070
1071   m_v_out_high = info->vP - ((m_type & DISC_OP_AMP_IS_NORTON) ? OP_AMP_NORTON_VBE : OP_AMP_VP_RAIL_OFFSET);
1072   m_v_cap      = 0;
1073
1074   this->step();
1075}
1076
1077
1078/************************************************************************
1079 *
1080 * DSS_SAWTOOTHWAVE - Usage of node_description values for step function
1081 *
1082 * input0    - Enable input value
1083 * input1    - Frequency input value
1084 * input2    - Amplitde input value
1085 * input3    - DC Bias Value
1086 * input4    - Gradient
1087 * input5    - Initial Phase
1088 *
1089 ************************************************************************/
1090#define DSS_SAWTOOTHWAVE__ENABLE    DISCRETE_INPUT(0)
1091#define DSS_SAWTOOTHWAVE__FREQ      DISCRETE_INPUT(1)
1092#define DSS_SAWTOOTHWAVE__AMP       DISCRETE_INPUT(2)
1093#define DSS_SAWTOOTHWAVE__BIAS      DISCRETE_INPUT(3)
1094#define DSS_SAWTOOTHWAVE__GRAD      DISCRETE_INPUT(4)
1095#define DSS_SAWTOOTHWAVE__PHASE     DISCRETE_INPUT(5)
1096
1097DISCRETE_STEP(dss_sawtoothwave)
1098{
1099   double v_out;
1100
1101   if(DSS_SAWTOOTHWAVE__ENABLE)
1102   {
1103      v_out = (m_type == 0) ? m_phase * (DSS_SAWTOOTHWAVE__AMP / (2.0 * M_PI)) : DSS_SAWTOOTHWAVE__AMP - (m_phase * (DSS_SAWTOOTHWAVE__AMP / (2.0 * M_PI)));
1104      v_out -= DSS_SAWTOOTHWAVE__AMP / 2.0;
1105      /* Add DC Bias component */
1106      v_out = v_out + DSS_SAWTOOTHWAVE__BIAS;
1107   }
1108   else
1109   {
1110      v_out = 0;
1111   }
1112   set_output(0, v_out);
1113
1114   /* Work out the phase step based on phase/freq & sample rate */
1115   /* The enable input only curtails output, phase rotation     */
1116   /* still occurs                                              */
1117   /*     phase step = 2Pi/(output period/sample period)        */
1118   /*                    boils out to                           */
1119   /*     phase step = (2Pi*output freq)/sample freq)           */
1120   /* Also keep the new phasor in the 2Pi range.                */
1121   m_phase = fmod((m_phase + ((2.0 * M_PI * DSS_SAWTOOTHWAVE__FREQ) / this->sample_rate())), 2.0 * M_PI);
1122}
1123
1124DISCRETE_RESET(dss_sawtoothwave)
1125{
1126   double start;
1127
1128   /* Establish starting phase, convert from degrees to radians */
1129   start = (DSS_SAWTOOTHWAVE__PHASE / 360.0) * (2.0 * M_PI);
1130   /* Make sure its always mod 2Pi */
1131   m_phase = fmod(start, 2.0 * M_PI);
1132
1133   /* Invert gradient depending on sawtooth type /|/|/|/|/| or |\|\|\|\|\ */
1134   m_type = (DSS_SAWTOOTHWAVE__GRAD) ? 1 : 0;
1135
1136   /* Step the node to set the output */
1137   this->step();
1138}
1139
1140
1141/************************************************************************
1142 *
1143 * DSS_SCHMITT_OSC - Schmitt feedback oscillator
1144 *
1145 * input0    - Enable input value
1146 * input1    - Vin
1147 * input2    - Amplitude
1148 *
1149 * also passed discrete_schmitt_osc_disc structure
1150 *
1151 * Mar 2004, D Renaud.
1152 ************************************************************************/
1153#define DSS_SCHMITT_OSC__ENABLE (int)DISCRETE_INPUT(0)
1154#define DSS_SCHMITT_OSC__VIN    DISCRETE_INPUT(1)
1155#define DSS_SCHMITT_OSC__AMP    DISCRETE_INPUT(2)
1156
1157DISCRETE_STEP(dss_schmitt_osc)
1158{
1159   DISCRETE_DECLARE_INFO(discrete_schmitt_osc_desc)
1160
1161   double supply, v_cap, new_vCap, t, exponent;
1162   double v_out = 0;
1163
1164   /* We will always oscillate.  The enable just affects the output. */
1165   v_cap    = m_v_cap;
1166   exponent = m_exponent;
1167
1168   /* Keep looping until all toggling in time sample is used up. */
1169   do
1170   {
1171      t = 0;
1172      /* The charging voltage to the cap is the sum of the input voltage and the gate
1173       * output voltage in the ratios determined by their resistors in a divider network.
1174       * The input voltage is selectable as straight voltage in or logic level that will
1175       * use vGate as its voltage.  Note that ration_in is just the ratio of the total
1176       * voltage and needs to be multipled by the input voltage.  ratio_feedback has
1177       * already been multiplied by vGate to save time because that voltage never changes. */
1178      supply   = m_input_is_voltage ? m_ration_in * DSS_SCHMITT_OSC__VIN : (DSS_SCHMITT_OSC__VIN ? m_ration_in * info->vGate : 0);
1179      supply  += (m_state ? m_ratio_feedback : 0);
1180      new_vCap = v_cap + ((supply - v_cap) * exponent);
1181      if (m_state)
1182      {
1183         /* Charging */
1184         /* has it charged past upper limit? */
1185         if (new_vCap > info->trshRise)
1186         {
1187            /* calculate the overshoot time */
1188            t = m_rc * log(1.0 / (1.0 - ((new_vCap - info->trshRise) / (info->vGate - v_cap))));
1189            /* calculate new exponent because of reduced time */
1190            exponent = RC_CHARGE_EXP_DT(m_rc, t);
1191            v_cap    = new_vCap = info->trshRise;
1192            m_state = 0;
1193         }
1194      }
1195      else
1196      {
1197         /* Discharging */
1198         /* has it discharged past lower limit? */
1199         if (new_vCap < info->trshFall)
1200         {
1201            /* calculate the overshoot time */
1202            t = m_rc * log(1.0 / (1.0 - ((info->trshFall - new_vCap) / v_cap)));
1203            /* calculate new exponent because of reduced time */
1204            exponent = RC_CHARGE_EXP_DT(m_rc, t);
1205            v_cap    = new_vCap = info->trshFall;
1206            m_state = 1;
1207         }
1208      }
1209   } while(t);
1210
1211   m_v_cap = new_vCap;
1212
1213   switch (m_enable_type)
1214   {
1215      case DISC_SCHMITT_OSC_ENAB_IS_AND:
1216         v_out = DSS_SCHMITT_OSC__ENABLE && m_state;
1217         break;
1218      case DISC_SCHMITT_OSC_ENAB_IS_NAND:
1219         v_out = !(DSS_SCHMITT_OSC__ENABLE && m_state);
1220         break;
1221      case DISC_SCHMITT_OSC_ENAB_IS_OR:
1222         v_out = DSS_SCHMITT_OSC__ENABLE || m_state;
1223         break;
1224      case DISC_SCHMITT_OSC_ENAB_IS_NOR:
1225         v_out = !(DSS_SCHMITT_OSC__ENABLE || m_state);
1226         break;
1227   }
1228   v_out *= DSS_SCHMITT_OSC__AMP;
1229   set_output(0, v_out);
1230}
1231
1232DISCRETE_RESET(dss_schmitt_osc)
1233{
1234   DISCRETE_DECLARE_INFO(discrete_schmitt_osc_desc)
1235
1236   double rSource;
1237
1238   m_enable_type      =  info->options & DISC_SCHMITT_OSC_ENAB_MASK;
1239   m_input_is_voltage = (info->options & DISC_SCHMITT_OSC_IN_IS_VOLTAGE) ? 1 : 0;
1240
1241   /* The 2 resistors make a voltage divider, so their ratios add together
1242    * to make the charging voltage. */
1243   m_ration_in      = info->rFeedback / (info->rIn + info->rFeedback);
1244   m_ratio_feedback = info->rIn / (info->rIn + info->rFeedback) * info->vGate;
1245
1246   /* The voltage source resistance works out to the 2 resistors in parallel.
1247    * So use this for the RC charge constant. */
1248   rSource     = 1.0 / ((1.0 / info->rIn) + (1.0 / info->rFeedback));
1249   m_rc = rSource * info->c;
1250   m_exponent = RC_CHARGE_EXP(m_rc);
1251
1252   /* Cap is at 0V on power up.  Causing output to be high. */
1253   m_v_cap = 0;
1254   m_state = 1;
1255
1256   set_output(0, info->options ? 0 : DSS_SCHMITT_OSC__AMP);
1257}
1258
1259
1260/************************************************************************
1261 *
1262 * DSS_SINEWAVE - Usage of node_description values for step function
1263 *
1264 * input0    - Enable input value
1265 * input1    - Frequency input value
1266 * input2    - Amplitude input value
1267 * input3    - DC Bias
1268 * input4    - Starting phase
1269 *
1270 ************************************************************************/
1271#define DSS_SINEWAVE__ENABLE    DISCRETE_INPUT(0)
1272#define DSS_SINEWAVE__FREQ      DISCRETE_INPUT(1)
1273#define DSS_SINEWAVE__AMPL      DISCRETE_INPUT(2)
1274#define DSS_SINEWAVE__BIAS      DISCRETE_INPUT(3)
1275#define DSS_SINEWAVE__PHASE     DISCRETE_INPUT(4)
1276
1277DISCRETE_STEP(dss_sinewave)
1278{
1279   /* Set the output */
1280   if(DSS_SINEWAVE__ENABLE)
1281   {
1282      set_output(0, (DSS_SINEWAVE__AMPL / 2.0) * sin(m_phase) + DSS_SINEWAVE__BIAS);
1283      /* Add DC Bias component */
1284   }
1285   else
1286   {
1287      set_output(0, 0);
1288   }
1289
1290   /* Work out the phase step based on phase/freq & sample rate */
1291   /* The enable input only curtails output, phase rotation     */
1292   /* still occurs                                              */
1293   /*     phase step = 2Pi/(output period/sample period)        */
1294   /*                    boils out to                           */
1295   /*     phase step = (2Pi*output freq)/sample freq)           */
1296   /* Also keep the new phasor in the 2Pi range.                */
1297   m_phase=fmod((m_phase + ((2.0 * M_PI * DSS_SINEWAVE__FREQ) / this->sample_rate())), 2.0 * M_PI);
1298}
1299
1300DISCRETE_RESET(dss_sinewave)
1301{
1302   double start;
1303
1304   /* Establish starting phase, convert from degrees to radians */
1305   start = (DSS_SINEWAVE__PHASE / 360.0) * (2.0 * M_PI);
1306   /* Make sure its always mod 2Pi */
1307   m_phase = fmod(start, 2.0 * M_PI);
1308   /* Step the output to make it correct */
1309   this->step();
1310}
1311
1312
1313/************************************************************************
1314 *
1315 * DSS_SQUAREWAVE - Usage of node_description values for step function
1316 *
1317 * input0    - Enable input value
1318 * input1    - Frequency input value
1319 * input2    - Amplitude input value
1320 * input3    - Duty Cycle
1321 * input4    - DC Bias level
1322 * input5    - Start Phase
1323 *
1324 ************************************************************************/
1325#define DSS_SQUAREWAVE__ENABLE  DISCRETE_INPUT(0)
1326#define DSS_SQUAREWAVE__FREQ    DISCRETE_INPUT(1)
1327#define DSS_SQUAREWAVE__AMP     DISCRETE_INPUT(2)
1328#define DSS_SQUAREWAVE__DUTY    DISCRETE_INPUT(3)
1329#define DSS_SQUAREWAVE__BIAS    DISCRETE_INPUT(4)
1330#define DSS_SQUAREWAVE__PHASE   DISCRETE_INPUT(5)
1331
1332DISCRETE_STEP(dss_squarewave)
1333{
1334   /* Establish trigger phase from duty */
1335   m_trigger=((100-DSS_SQUAREWAVE__DUTY)/100)*(2.0*M_PI);
1336
1337   /* Set the output */
1338   if(DSS_SQUAREWAVE__ENABLE)
1339   {
1340      if(m_phase>m_trigger)
1341         set_output(0, DSS_SQUAREWAVE__AMP / 2.0 + DSS_SQUAREWAVE__BIAS);
1342      else
1343         set_output(0, - DSS_SQUAREWAVE__AMP / 2.0 + DSS_SQUAREWAVE__BIAS);
1344      /* Add DC Bias component */
1345   }
1346   else
1347   {
1348      set_output(0, 0);
1349   }
1350
1351   /* Work out the phase step based on phase/freq & sample rate */
1352   /* The enable input only curtails output, phase rotation     */
1353   /* still occurs                                              */
1354   /*     phase step = 2Pi/(output period/sample period)        */
1355   /*                    boils out to                           */
1356   /*     phase step = (2Pi*output freq)/sample freq)           */
1357   /* Also keep the new phasor in the 2Pi range.                */
1358   m_phase=fmod(m_phase + ((2.0 * M_PI * DSS_SQUAREWAVE__FREQ) / this->sample_rate()), 2.0 * M_PI);
1359}
1360
1361DISCRETE_RESET(dss_squarewave)
1362{
1363   double start;
1364
1365   /* Establish starting phase, convert from degrees to radians */
1366   start = (DSS_SQUAREWAVE__PHASE / 360.0) * (2.0 * M_PI);
1367   /* Make sure its always mod 2Pi */
1368   m_phase = fmod(start, 2.0 * M_PI);
1369
1370   /* Step the output */
1371   this->step();
1372}
1373
1374/************************************************************************
1375 *
1376 * DSS_SQUAREWFIX - Usage of node_description values for step function
1377 *
1378 * input0    - Enable input value
1379 * input1    - Frequency input value
1380 * input2    - Amplitude input value
1381 * input3    - Duty Cycle
1382 * input4    - DC Bias level
1383 * input5    - Start Phase
1384 *
1385 ************************************************************************/
1386#define DSS_SQUAREWFIX__ENABLE  DISCRETE_INPUT(0)
1387#define DSS_SQUAREWFIX__FREQ    DISCRETE_INPUT(1)
1388#define DSS_SQUAREWFIX__AMP     DISCRETE_INPUT(2)
1389#define DSS_SQUAREWFIX__DUTY    DISCRETE_INPUT(3)
1390#define DSS_SQUAREWFIX__BIAS    DISCRETE_INPUT(4)
1391#define DSS_SQUAREWFIX__PHASE   DISCRETE_INPUT(5)
1392
1393DISCRETE_STEP(dss_squarewfix)
1394{
1395   m_t_left -= m_sample_step;
1396
1397   /* The enable input only curtails output, phase rotation still occurs */
1398   while (m_t_left <= 0)
1399   {
1400      m_flip_flop = m_flip_flop ? 0 : 1;
1401      m_t_left   += m_flip_flop ? m_t_on : m_t_off;
1402   }
1403
1404   if(DSS_SQUAREWFIX__ENABLE)
1405   {
1406      /* Add gain and DC Bias component */
1407
1408      m_t_off  = 1.0 / DSS_SQUAREWFIX__FREQ;  /* cycle time */
1409      m_t_on   = m_t_off * (DSS_SQUAREWFIX__DUTY / 100.0);
1410      m_t_off -= m_t_on;
1411
1412      set_output(0, (m_flip_flop ? DSS_SQUAREWFIX__AMP / 2.0 : -(DSS_SQUAREWFIX__AMP / 2.0)) + DSS_SQUAREWFIX__BIAS);
1413   }
1414   else
1415   {
1416      set_output(0, 0);
1417   }
1418}
1419
1420DISCRETE_RESET(dss_squarewfix)
1421{
1422   m_sample_step = 1.0 / this->sample_rate();
1423   m_flip_flop   = 1;
1424
1425   /* Do the intial time shift and convert freq to off/on times */
1426   m_t_off   = 1.0 / DSS_SQUAREWFIX__FREQ; /* cycle time */
1427   m_t_left  = DSS_SQUAREWFIX__PHASE / 360.0;  /* convert start phase to % */
1428   m_t_left  = m_t_left - (int)m_t_left;   /* keep % between 0 & 1 */
1429   m_t_left  = (m_t_left < 0) ? 1.0 + m_t_left : m_t_left; /* if - then flip to + phase */
1430   m_t_left *= m_t_off;
1431   m_t_on    = m_t_off * (DSS_SQUAREWFIX__DUTY / 100.0);
1432   m_t_off  -= m_t_on;
1433
1434   m_t_left = -m_t_left;
1435
1436   /* toggle output and work out intial time shift */
1437   while (m_t_left <= 0)
1438   {
1439      m_flip_flop = m_flip_flop ? 0 : 1;
1440      m_t_left   += m_flip_flop ? m_t_on : m_t_off;
1441   }
1442
1443   /* Step the output */
1444   this->step();
1445}
1446
1447
1448/************************************************************************
1449 *
1450 * DSS_SQUAREWAVE2 - Usage of node_description values
1451 *
1452 * input0    - Enable input value
1453 * input1    - Amplitude input value
1454 * input2    - OFF Time
1455 * input3    - ON Time
1456 * input4    - DC Bias level
1457 * input5    - Initial Time Shift
1458 *
1459 ************************************************************************/
1460#define DSS_SQUAREWAVE2__ENABLE DISCRETE_INPUT(0)
1461#define DSS_SQUAREWAVE2__AMP    DISCRETE_INPUT(1)
1462#define DSS_SQUAREWAVE2__T_OFF  DISCRETE_INPUT(2)
1463#define DSS_SQUAREWAVE2__T_ON   DISCRETE_INPUT(3)
1464#define DSS_SQUAREWAVE2__BIAS   DISCRETE_INPUT(4)
1465#define DSS_SQUAREWAVE2__SHIFT  DISCRETE_INPUT(5)
1466
1467DISCRETE_STEP(dss_squarewave2)
1468{
1469   double newphase;
1470
1471   if(DSS_SQUAREWAVE2__ENABLE)
1472   {
1473      /* Establish trigger phase from time periods */
1474      m_trigger = (DSS_SQUAREWAVE2__T_OFF / (DSS_SQUAREWAVE2__T_OFF + DSS_SQUAREWAVE2__T_ON)) * (2.0 * M_PI);
1475
1476      /* Work out the phase step based on phase/freq & sample rate */
1477      /* The enable input only curtails output, phase rotation     */
1478      /* still occurs                                              */
1479
1480      /*     phase step = 2Pi/(output period/sample period)        */
1481      /*                    boils out to                           */
1482      /*     phase step = 2Pi/(output period*sample freq)          */
1483      newphase = m_phase + ((2.0 * M_PI) / ((DSS_SQUAREWAVE2__T_OFF + DSS_SQUAREWAVE2__T_ON) * this->sample_rate()));
1484      /* Keep the new phasor in the 2Pi range.*/
1485      m_phase = fmod(newphase, 2.0 * M_PI);
1486
1487      /* Add DC Bias component */
1488      if(m_phase>m_trigger)
1489         set_output(0, DSS_SQUAREWAVE2__AMP / 2.0  + DSS_SQUAREWAVE2__BIAS);
1490      else
1491         set_output(0, -DSS_SQUAREWAVE2__AMP / 2.0 + DSS_SQUAREWAVE2__BIAS);
1492   }
1493   else
1494   {
1495      set_output(0, 0);
1496   }
1497}
1498
1499DISCRETE_RESET(dss_squarewave2)
1500{
1501   double start;
1502
1503   /* Establish starting phase, convert from degrees to radians */
1504   /* Only valid if we have set the on/off time                 */
1505   if((DSS_SQUAREWAVE2__T_OFF + DSS_SQUAREWAVE2__T_ON) != 0.0)
1506      start = (DSS_SQUAREWAVE2__SHIFT / (DSS_SQUAREWAVE2__T_OFF + DSS_SQUAREWAVE2__T_ON)) * (2.0 * M_PI);
1507   else
1508      start = 0.0;
1509   /* Make sure its always mod 2Pi */
1510   m_phase = fmod(start, 2.0 * M_PI);
1511
1512   /* Step the output */
1513   this->step();
1514}
1515
1516/************************************************************************
1517 *
1518 * DSS_INVERTER_OSC - Usage of node_description values
1519 *
1520 * input0    - Enable input value
1521 * input1    - RC Resistor
1522 * input2    - RP Resistor
1523 * input3    - C Capacitor
1524 * input4    - Desc
1525 *
1526 ************************************************************************/
1527
1528/*
1529 * Taken from the transfer characteristerics diagram in CD4049UB datasheet (TI)
1530 * There is no default trigger point and vI-vO is a continuous function
1531 */
1532
1533inline double DISCRETE_CLASS_FUNC(dss_inverter_osc, tftab)(double x)
1534{
1535   DISCRETE_DECLARE_INFO(description)
1536
1537   x = x / info->vB;
1538   if (x > 0)
1539      return info->vB * exp(-mc_tf_a * pow(x, mc_tf_b));
1540   else
1541      return info->vB;
1542}
1543
1544inline double DISCRETE_CLASS_FUNC(dss_inverter_osc, tf)(double x)
1545{
1546   DISCRETE_DECLARE_INFO(description)
1547
1548   if (x < 0.0)
1549      return info->vB;
1550   else if (x <= info->vB)
1551      return mc_tf_tab[(int)((double)(DSS_INV_TAB_SIZE - 1) * x / info->vB)];
1552   else
1553      return mc_tf_tab[DSS_INV_TAB_SIZE - 1];
1554}
1555
1556DISCRETE_STEP(dss_inverter_osc)
1557{
1558   DISCRETE_DECLARE_INFO(description)
1559   double diff, vG1, vG2, vG3, vI;
1560   double vMix, rMix;
1561   int clamped;
1562   double v_out;
1563
1564   /* Get new state */
1565   vI = mc_v_cap + mc_v_g2_old;
1566   switch (info->options & TYPE_MASK)
1567   {
1568      case IS_TYPE1:
1569      case IS_TYPE3:
1570         vG1 = this->tf(vI);
1571         vG2 = this->tf(vG1);
1572         vG3 = this->tf(vG2);
1573         break;
1574      case IS_TYPE2:
1575         vG1 = 0;
1576         vG3 = this->tf(vI);
1577         vG2 = this->tf(vG3);
1578         break;
1579      case IS_TYPE4:
1580         vI  = MIN(I_ENABLE(), vI + 0.7);
1581         vG1 = 0;
1582         vG3 = this->tf(vI);
1583         vG2 = this->tf(vG3);
1584         break;
1585      case IS_TYPE5:
1586         vI  = MAX(I_ENABLE(), vI - 0.7);
1587         vG1 = 0;
1588         vG3 = this->tf(vI);
1589         vG2 = this->tf(vG3);
1590         break;
1591      default:
1592         fatalerror("DISCRETE_INVERTER_OSC - Wrong type on NODE_%02d\n", this->index());
1593   }
1594
1595   clamped = 0;
1596   if (info->clamp >= 0.0)
1597   {
1598      if (vI < -info->clamp)
1599      {
1600         vI = -info->clamp;
1601         clamped = 1;
1602      }
1603      else if (vI > info->vB+info->clamp)
1604      {
1605         vI = info->vB + info->clamp;
1606         clamped = 1;
1607      }
1608   }
1609
1610   switch (info->options & TYPE_MASK)
1611   {
1612      case IS_TYPE1:
1613      case IS_TYPE2:
1614      case IS_TYPE3:
1615         if (clamped)
1616         {
1617            double ratio = mc_rp / (mc_rp + mc_r1);
1618            diff = vG3 * (ratio)
1619                  - (mc_v_cap + vG2)
1620                  + vI * (1.0 - ratio);
1621            diff = diff - diff * mc_wc;
1622         }
1623         else
1624         {
1625            diff = vG3 - (mc_v_cap + vG2);
1626            diff = diff - diff * mc_w;
1627         }
1628         break;
1629      case IS_TYPE4:
1630         /*  FIXME handle r2 = 0  */
1631         rMix = (mc_r1 * mc_r2) / (mc_r1 + mc_r2);
1632         vMix = rMix* ((vG3 - vG2) / mc_r1 + (I_MOD() -vG2) / mc_r2);
1633         if (vMix < (vI-vG2-0.7))
1634         {
1635            rMix = 1.0 / rMix + 1.0 / mc_rp;
1636            rMix = 1.0 / rMix;
1637            vMix = rMix* ( (vG3-vG2) / mc_r1 + (I_MOD() - vG2) / mc_r2
1638                  + (vI - 0.7 - vG2) / mc_rp);
1639         }
1640         diff = vMix - mc_v_cap;
1641         diff = diff - diff * exp(-this->sample_time() / (mc_c * rMix));
1642         break;
1643      case IS_TYPE5:
1644         /*  FIXME handle r2 = 0  */
1645         rMix = (mc_r1 * mc_r2) / (mc_r1 + mc_r2);
1646         vMix = rMix* ((vG3 - vG2) / mc_r1 + (I_MOD() - vG2) / mc_r2);
1647         if (vMix > (vI -vG2 + 0.7))
1648         {
1649            rMix = 1.0 / rMix + 1.0 / mc_rp;
1650            rMix = 1.0 / rMix;
1651            vMix = rMix * ( (vG3 - vG2) / mc_r1 + (I_MOD() - vG2) / mc_r2
1652                  + (vI + 0.7 - vG2) / mc_rp);
1653         }
1654         diff = vMix - mc_v_cap;
1655         diff = diff - diff * exp(-this->sample_time()/(mc_c * rMix));
1656         break;
1657      default:
1658         fatalerror("DISCRETE_INVERTER_OSC - Wrong type on NODE_%02d\n", this->index());
1659   }
1660
1661   mc_v_cap   += diff;
1662   mc_v_g2_old = vG2;
1663
1664   if ((info->options & TYPE_MASK) == IS_TYPE3)
1665      v_out = vG1;
1666   else
1667      v_out = vG3;
1668
1669   if (info->options & OUT_IS_LOGIC)
1670      v_out = (v_out > info->vInFall);
1671
1672   set_output(0, v_out);
1673}
1674
1675DISCRETE_RESET(dss_inverter_osc)
1676{
1677   DISCRETE_DECLARE_INFO(description)
1678
1679   int i;
1680
1681   /* exponent */
1682   mc_w  = exp(-this->sample_time() / (I_RC() * I_C()));
1683   mc_wc = exp(-this->sample_time() / ((I_RC() * I_RP()) / (I_RP() + I_RC()) * I_C()));
1684   set_output(0, 0);
1685   mc_v_cap    = 0;
1686   mc_v_g2_old = 0;
1687   mc_rp   = I_RP();
1688   mc_r1   = I_RC();
1689   mc_r2   = I_R2();
1690   mc_c    = I_C();
1691   mc_tf_b = (log(0.0 - log(info->vOutLow/info->vB)) - log(0.0 - log((info->vOutHigh/info->vB))) ) / log(info->vInRise / info->vInFall);
1692   mc_tf_a = log(0.0 - log(info->vOutLow/info->vB)) - mc_tf_b * log(info->vInRise/info->vB);
1693   mc_tf_a = exp(mc_tf_a);
1694
1695   for (i = 0; i < DSS_INV_TAB_SIZE; i++)
1696   {
1697      mc_tf_tab[i] = this->tftab((double)i / (double)(DSS_INV_TAB_SIZE - 1) * info->vB);
1698   }
1699}
1700
1701/************************************************************************
1702 *
1703 * DSS_TRIANGLEWAVE - Usage of node_description values for step function
1704 *
1705 * input0    - Enable input value
1706 * input1    - Frequency input value
1707 * input2    - Amplitde input value
1708 * input3    - DC Bias value
1709 * input4    - Initial Phase
1710 *
1711 ************************************************************************/
1712#define DSS_TRIANGLEWAVE__ENABLE    DISCRETE_INPUT(0)
1713#define DSS_TRIANGLEWAVE__FREQ      DISCRETE_INPUT(1)
1714#define DSS_TRIANGLEWAVE__AMP       DISCRETE_INPUT(2)
1715#define DSS_TRIANGLEWAVE__BIAS      DISCRETE_INPUT(3)
1716#define DSS_TRIANGLEWAVE__PHASE     DISCRETE_INPUT(4)
1717
1718DISCRETE_STEP(dss_trianglewave)
1719{
1720   if(DSS_TRIANGLEWAVE__ENABLE)
1721   {
1722      double v_out = m_phase < M_PI ? (DSS_TRIANGLEWAVE__AMP * (m_phase / (M_PI / 2.0) - 1.0)) / 2.0 :
1723                           (DSS_TRIANGLEWAVE__AMP * (3.0 - m_phase / (M_PI / 2.0))) / 2.0 ;
1724
1725      /* Add DC Bias component */
1726      v_out  += DSS_TRIANGLEWAVE__BIAS;
1727      set_output(0, v_out);
1728   }
1729   else
1730   {
1731      set_output(0, 0);
1732   }
1733
1734   /* Work out the phase step based on phase/freq & sample rate */
1735   /* The enable input only curtails output, phase rotation     */
1736   /* still occurs                                              */
1737   /*     phase step = 2Pi/(output period/sample period)        */
1738   /*                    boils out to                           */
1739   /*     phase step = (2Pi*output freq)/sample freq)           */
1740   /* Also keep the new phasor in the 2Pi range.                */
1741   m_phase=fmod((m_phase + ((2.0 * M_PI * DSS_TRIANGLEWAVE__FREQ) / this->sample_rate())), 2.0 * M_PI);
1742}
1743
1744DISCRETE_RESET(dss_trianglewave)
1745{
1746   double start;
1747
1748   /* Establish starting phase, convert from degrees to radians */
1749   start = (DSS_TRIANGLEWAVE__PHASE / 360.0) * (2.0 * M_PI);
1750   /* Make sure its always mod 2Pi */
1751   m_phase=fmod(start, 2.0 * M_PI);
1752
1753   /* Step to set the output */
1754   this->step();
1755}
1756
1757
1758/************************************************************************
1759 *
1760 * DSS_ADSR - Attack Decay Sustain Release
1761 *
1762 * input0    - Enable input value
1763 * input1    - Trigger value
1764 * input2    - gain scaling factor
1765 *
1766 ************************************************************************/
1767#define DSS_ADSR__ENABLE    DISCRETE_INPUT(0)
1768
1769DISCRETE_STEP(dss_adsrenv)
1770{
1771   if(DSS_ADSR__ENABLE)
1772   {
1773      set_output(0, 0);
1774   }
1775   else
1776   {
1777      set_output(0, 0);
1778   }
1779}
1780
1781
1782DISCRETE_RESET(dss_adsrenv)
1783{
1784   this->step();
1785}
trunk/src/emu/sound/disc_sys.c
r28731r28732
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 *  (c) D.Renaud 2003-2004
9 *
10 ************************************************************************
11 *
12 * DSO_OUTPUT            - Output node
13 * DSO_TASK              - Task node
14 *
15 * Task and list routines
16 *
17 ************************************************************************/
18
19
20
21
22/*************************************
23 *
24 *  Task node (main task execution)
25 *
26 *************************************/
27
28
29DISCRETE_START( dso_csvlog )
30{
31   int log_num, node_num;
32
33   log_num = m_device->same_module_index(*this);
34   m_sample_num = 0;
35
36   sprintf(m_name, "discrete_%s_%d.csv", m_device->tag(), log_num);
37   m_csv_file = fopen(m_name, "w");
38   /* Output some header info */
39   fprintf(m_csv_file, "\"MAME Discrete System Node Log\"\n");
40   fprintf(m_csv_file, "\"Log Version\", 1.0\n");
41   fprintf(m_csv_file, "\"Sample Rate\", %d\n", this->sample_rate());
42   fprintf(m_csv_file, "\n");
43   fprintf(m_csv_file, "\"Sample\"");
44   for (node_num = 0; node_num < this->active_inputs(); node_num++)
45   {
46      fprintf(m_csv_file, ", \"NODE_%2d\"", NODE_INDEX(this->input_node(node_num)));
47   }
48   fprintf(m_csv_file, "\n");
49}
50
51DISCRETE_STOP( dso_csvlog )
52{
53   /* close any csv files */
54   if (m_csv_file)
55      fclose(m_csv_file);
56}
57
58DISCRETE_STEP( dso_csvlog )
59{
60   int nodenum;
61
62   /* Dump any csv logs */
63   fprintf(m_csv_file, "%" I64FMT "d", ++m_sample_num);
64   for (nodenum = 0; nodenum < this->active_inputs(); nodenum++)
65   {
66      fprintf(m_csv_file, ", %f", *this->m_input[nodenum]);
67   }
68   fprintf(m_csv_file, "\n");
69}
70
71DISCRETE_RESET( dso_csvlog )
72{
73   this->step();
74}
75
76
77DISCRETE_START( dso_wavlog )
78{
79   int log_num;
80
81   log_num = m_device->same_module_index(*this);
82   sprintf(m_name, "discrete_%s_%d.wav", m_device->tag(), log_num);
83   m_wavfile = wav_open(m_name, sample_rate(), active_inputs()/2);
84}
85
86DISCRETE_STOP( dso_wavlog )
87{
88   /* close any wave files */
89   if (m_wavfile)
90      wav_close(m_wavfile);
91}
92
93DISCRETE_STEP( dso_wavlog )
94{
95   double val;
96   INT16 wave_data_l, wave_data_r;
97
98   /* Dump any wave logs */
99   /* get nodes to be logged and apply gain, then clip to 16 bit */
100   val = DISCRETE_INPUT(0) * DISCRETE_INPUT(1);
101   val = (val < -32768) ? -32768 : (val > 32767) ? 32767 : val;
102   wave_data_l = (INT16)val;
103   if (this->active_inputs() == 2)
104   {
105      /* DISCRETE_WAVLOG1 */
106      wav_add_data_16(m_wavfile, &wave_data_l, 1);
107   }
108   else
109   {
110      /* DISCRETE_WAVLOG2 */
111      val = DISCRETE_INPUT(2) * DISCRETE_INPUT(3);
112      val = (val < -32768) ? -32768 : (val > 32767) ? 32767 : val;
113      wave_data_r = (INT16)val;
114
115      wav_add_data_16lr(m_wavfile, &wave_data_l, &wave_data_r, 1);
116   }
117}
118
119DISCRETE_RESET( dso_wavlog )
120{
121   this->step();
122}
trunk/src/emu/sound/disc_inp.c
r28731r28732
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 * DSS_ADJUSTMENT        - UI Mapped adjustable input
12 * DSS_CONSTANT          - Node based constant - Do we need this ???
13 * DSS_INPUT_x           - Input devices
14 * DSS_INPUT_STREAM      - Connects external streams to the discrete system
15 *
16 ************************************************************************/
17
18
19#define DSS_INPUT__GAIN     DISCRETE_INPUT(0)
20#define DSS_INPUT__OFFSET   DISCRETE_INPUT(1)
21#define DSS_INPUT__INIT     DISCRETE_INPUT(2)
22
23READ8_DEVICE_HANDLER(discrete_sound_r)
24{
25   discrete_device *disc_device = downcast<discrete_device *>(device);
26   return  disc_device->read( space, offset, 0xff);
27}
28
29
30WRITE8_DEVICE_HANDLER(discrete_sound_w)
31{
32   discrete_device *disc_device = downcast<discrete_device *>(device);
33   disc_device->write(space, offset, data, 0xff);
34}
35
36/************************************************************************
37 *
38 * DSS_ADJUSTMENT - UI Adjustable constant node to emulate trimmers
39 *
40 * input[0]    - Enable
41 * input[1]    - Minimum value
42 * input[2]    - Maximum value
43 * input[3]    - Log/Linear 0=Linear !0=Log
44 * input[4]    - Input Port number
45 * input[5]    -
46 * input[6]    -
47 *
48 ************************************************************************/
49#define DSS_ADJUSTMENT__MIN     DISCRETE_INPUT(0)
50#define DSS_ADJUSTMENT__MAX     DISCRETE_INPUT(1)
51#define DSS_ADJUSTMENT__LOG     DISCRETE_INPUT(2)
52#define DSS_ADJUSTMENT__PORT    DISCRETE_INPUT(3)
53#define DSS_ADJUSTMENT__PMIN    DISCRETE_INPUT(4)
54#define DSS_ADJUSTMENT__PMAX    DISCRETE_INPUT(5)
55
56DISCRETE_STEP(dss_adjustment)
57{
58   INT32  rawportval = m_port->read();
59
60   /* only recompute if the value changed from last time */
61   if (UNEXPECTED(rawportval != m_lastpval))
62   {
63      double portval   = (double)(rawportval - m_pmin) * m_pscale;
64      double scaledval = portval * m_scale + m_min;
65
66      m_lastpval = rawportval;
67      if (DSS_ADJUSTMENT__LOG == 0)
68         set_output(0,  scaledval);
69      else
70         set_output(0,  pow(10, scaledval));
71   }
72}
73
74DISCRETE_RESET(dss_adjustment)
75{
76   double min, max;
77
78   astring fulltag;
79   m_port = m_device->machine().root_device().ioport(m_device->siblingtag(fulltag, (const char *)this->custom_data()).cstr());
80   if (m_port == NULL)
81      fatalerror("DISCRETE_ADJUSTMENT - NODE_%d has invalid tag\n", this->index());
82
83   m_lastpval = 0x7fffffff;
84   m_pmin     = DSS_ADJUSTMENT__PMIN;
85   m_pscale   = 1.0 / (double)(DSS_ADJUSTMENT__PMAX - DSS_ADJUSTMENT__PMIN);
86
87   /* linear scale */
88   if (DSS_ADJUSTMENT__LOG == 0)
89   {
90      m_min   = DSS_ADJUSTMENT__MIN;
91      m_scale = DSS_ADJUSTMENT__MAX - DSS_ADJUSTMENT__MIN;
92   }
93
94   /* logarithmic scale */
95   else
96   {
97      /* force minimum and maximum to be > 0 */
98      min = (DSS_ADJUSTMENT__MIN > 0) ? DSS_ADJUSTMENT__MIN : 1;
99      max = (DSS_ADJUSTMENT__MAX > 0) ? DSS_ADJUSTMENT__MAX : 1;
100      m_min   = log10(min);
101      m_scale = log10(max) - log10(min);
102   }
103
104   this->step();
105}
106
107
108/************************************************************************
109 *
110 * DSS_CONSTANT - This is a constant.
111 *
112 * input[0]    - Constant value
113 *
114 ************************************************************************/
115#define DSS_CONSTANT__INIT  DISCRETE_INPUT(0)
116
117DISCRETE_RESET(dss_constant)
118{
119   set_output(0, DSS_CONSTANT__INIT);
120}
121
122
123/************************************************************************
124 *
125 * DSS_INPUT_x    - Receives input from discrete_sound_w
126 *
127 * input[0]    - Gain value
128 * input[1]    - Offset value
129 * input[2]    - Starting Position
130 * input[3]    - Current data value
131 *
132 ************************************************************************/
133
134DISCRETE_RESET(dss_input_data)
135{
136   m_gain = DSS_INPUT__GAIN;
137   m_offset = DSS_INPUT__OFFSET;
138
139   m_data = DSS_INPUT__INIT;
140   set_output(0,  m_data * m_gain + m_offset);
141}
142
143void DISCRETE_CLASS_FUNC(dss_input_data, input_write)(int sub_node, UINT8 data )
144{
145   UINT8 new_data    = 0;
146
147   new_data = data;
148
149   if (m_data != new_data)
150   {
151      /* Bring the system up to now */
152      m_device->update_to_current_time();
153
154      m_data = new_data;
155
156      /* Update the node output here so we don't have to do it each step */
157      set_output(0,  m_data * m_gain + m_offset);
158   }
159}
160
161DISCRETE_RESET(dss_input_logic)
162{
163   m_gain = DSS_INPUT__GAIN;
164   m_offset = DSS_INPUT__OFFSET;
165
166   m_data = (DSS_INPUT__INIT == 0) ? 0 : 1;
167   set_output(0,  m_data * m_gain + m_offset);
168}
169
170void DISCRETE_CLASS_FUNC(dss_input_logic, input_write)(int sub_node, UINT8 data )
171{
172   UINT8 new_data    = 0;
173
174   new_data =  data ? 1 : 0;
175
176   if (m_data != new_data)
177   {
178      /* Bring the system up to now */
179      m_device->update_to_current_time();
180
181      m_data = new_data;
182
183      /* Update the node output here so we don't have to do it each step */
184      set_output(0,  m_data * m_gain + m_offset);
185   }
186}
187
188DISCRETE_RESET(dss_input_not)
189{
190   m_gain = DSS_INPUT__GAIN;
191   m_offset = DSS_INPUT__OFFSET;
192
193   m_data = (DSS_INPUT__INIT == 0) ? 1 : 0;
194   set_output(0,  m_data * m_gain + m_offset);
195}
196
197void DISCRETE_CLASS_FUNC(dss_input_not, input_write)(int sub_node, UINT8 data )
198{
199   UINT8 new_data    = 0;
200
201   new_data = data ? 0 : 1;
202
203   if (m_data != new_data)
204   {
205      /* Bring the system up to now */
206      m_device->update_to_current_time();
207
208      m_data = new_data;
209
210      /* Update the node output here so we don't have to do it each step */
211      set_output(0,  m_data * m_gain + m_offset);
212   }
213}
214
215DISCRETE_STEP(dss_input_pulse)
216{
217   /* Set a valid output */
218   set_output(0,  m_data);
219   /* Reset the input to default for the next cycle */
220   /* node order is now important */
221   m_data = DSS_INPUT__INIT;
222}
223
224DISCRETE_RESET(dss_input_pulse)
225{
226   m_data = (DSS_INPUT__INIT == 0) ? 0 : 1;
227   set_output(0,  m_data);
228}
229
230void DISCRETE_CLASS_FUNC(dss_input_pulse, input_write)(int sub_node, UINT8 data )
231{
232   UINT8 new_data    = 0;
233
234   new_data =  data ? 1 : 0;
235
236   if (m_data != new_data)
237   {
238      /* Bring the system up to now */
239      m_device->update_to_current_time();
240      m_data = new_data;
241   }
242}
243
244/************************************************************************
245 *
246 * DSS_INPUT_STREAM    - Receives input from a routed stream
247 *
248 * input[0]    - Input stream number
249 * input[1]    - Gain value
250 * input[2]    - Offset value
251 *
252 ************************************************************************/
253#define DSS_INPUT_STREAM__STREAM    DISCRETE_INPUT(0)
254#define DSS_INPUT_STREAM__GAIN      DISCRETE_INPUT(1)
255#define DSS_INPUT_STREAM__OFFSET    DISCRETE_INPUT(2)
256
257STREAM_UPDATE( discrete_dss_input_stream_node::static_stream_generate )
258{
259   reinterpret_cast<discrete_dss_input_stream_node *>(param)->stream_generate(inputs, outputs, samples);
260}
261
262void discrete_dss_input_stream_node::stream_generate(stream_sample_t **inputs, stream_sample_t **outputs, int samples)
263{
264   stream_sample_t *ptr = outputs[0];
265   int samplenum = samples;
266
267   while (samplenum-- > 0)
268      *(ptr++) = m_data;
269}
270DISCRETE_STEP(dss_input_stream)
271{
272   /* the context pointer is set to point to the current input stream data in discrete_stream_update */
273   if (EXPECTED(m_ptr))
274   {
275      set_output(0,  (*m_ptr) * m_gain + m_offset);
276      m_ptr++;
277   }
278   else
279      set_output(0,  0);
280}
281
282DISCRETE_RESET(dss_input_stream)
283{
284   m_ptr = NULL;
285   m_data = 0;
286}
287
288void DISCRETE_CLASS_FUNC(dss_input_stream, input_write)(int sub_node, UINT8 data )
289{
290   UINT8 new_data    = 0;
291
292   new_data =  data;
293
294   if (m_data != new_data)
295   {
296      if (m_is_buffered)
297      {
298         /* Bring the system up to now */
299         m_buffer_stream->update();
300
301         m_data = new_data;
302      }
303      else
304      {
305         /* Bring the system up to now */
306         m_device->update_to_current_time();
307
308         m_data = new_data;
309
310         /* Update the node output here so we don't have to do it each step */
311         set_output(0,  new_data * m_gain + m_offset);
312      }
313   }
314}
315
316DISCRETE_START(dss_input_stream)
317{
318   discrete_base_node::start();
319
320   /* Stream out number is set during start */
321   m_stream_in_number = DSS_INPUT_STREAM__STREAM;
322   m_gain = DSS_INPUT_STREAM__GAIN;
323   m_offset = DSS_INPUT_STREAM__OFFSET;
324   m_ptr = NULL;
325
326   m_is_buffered = is_buffered();
327   m_buffer_stream = NULL;
328}
329
330void DISCRETE_CLASS_NAME(dss_input_stream)::stream_start(void)
331{
332   if (m_is_buffered)
333   {
334      /* stream_buffered input only supported for sound devices */
335      discrete_sound_device *snd_device = downcast<discrete_sound_device *>(m_device);
336      //assert(DSS_INPUT_STREAM__STREAM < snd_device->m_input_stream_list.count());
337
338      m_buffer_stream = m_device->machine().sound().stream_alloc(*snd_device, 0, 1, this->sample_rate(), this, static_stream_generate);
339
340      snd_device->get_stream()->set_input(m_stream_in_number, m_buffer_stream);
341   }
342}
trunk/src/emu/sound/disc_mth.c
r28731r28732
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 *  (c) D.Renaud 2003-2004
9 *
10 ************************************************************************
11 *
12 * DST_ADDDER            - Multichannel adder
13 * DST_BITS_DECODE       - Decode Bits from input node
14 * DST_CLAMP             - Simple signal clamping circuit
15 * DST_COMP_ADDER        - Selectable parallel component circuit
16 * DST_DAC_R1            - R1 Ladder DAC with cap filtering
17 * DST_DIODE_MIX         - Diode mixer
18 * DST_DIVIDE            - Division function
19 * DST_GAIN              - Gain Factor
20 * DST_INTEGRATE         - Integration circuits
21 * DST_LOGIC_INV         - Logic level invertor
22 * DST_LOGIC_AND         - Logic AND gate 4 input
23 * DST_LOGIC_NAND        - Logic NAND gate 4 input
24 * DST_LOGIC_OR          - Logic OR gate 4 input
25 * DST_LOGIC_NOR         - Logic NOR gate 4 input
26 * DST_LOGIC_XOR         - Logic XOR gate 2 input
27 * DST_LOGIC_NXOR        - Logic NXOR gate 2 input
28 * DST_LOGIC_DFF         - Logic D-type flip/flop
29 * DST_LOGIC_JKFF        - Logic JK-type flip/flop
30 * DST_LOGIC_SHIFT       - Logic Shift Register
31 * DST_LOOKUP_TABLE      - Return value from lookup table
32 * DST_MIXER             - Final Mixer Stage
33 * DST_MULTIPLEX         - 1 of x Multiplexer/switch
34 * DST_ONESHOT           - One shot pulse generator
35 * DST_RAMP              - Ramp up/down
36 * DST_SAMPHOLD          - Sample & Hold Implementation
37 * DST_SWITCH            - Switch implementation
38 * DST_ASWITCH           - Analog switch
39 * DST_TRANSFORM         - Multiple math functions
40 * DST_OP_AMP            - Op Amp circuits
41 * DST_OP_AMP_1SHT       - Op Amp One Shot
42 * DST_TVCA_OP_AMP       - Triggered op amp voltage controlled amplifier
43 * DST_XTIME_BUFFER      - Buffer/Invertor gate implementation using X_TIME
44 * DST_XTIME_AND         - AND/NAND gate implementation using X_TIME
45 * DST_XTIME_OR          - OR/NOR gate implementation using X_TIME
46 * DST_XTIME_XOR         - XOR/XNOR gate implementation using X_TIME
47 *
48 ************************************************************************/
49
50#include <float.h>
51
52
53
54/************************************************************************
55 *
56 * DST_ADDER - This is a 4 channel input adder with enable function
57 *
58 * input[0]    - Enable input value
59 * input[1]    - Channel0 input value
60 * input[2]    - Channel1 input value
61 * input[3]    - Channel2 input value
62 * input[4]    - Channel3 input value
63 *
64 ************************************************************************/
65#define DST_ADDER__ENABLE   DISCRETE_INPUT(0)
66#define DST_ADDER__IN0      DISCRETE_INPUT(1)
67#define DST_ADDER__IN1      DISCRETE_INPUT(2)
68#define DST_ADDER__IN2      DISCRETE_INPUT(3)
69#define DST_ADDER__IN3      DISCRETE_INPUT(4)
70
71DISCRETE_STEP(dst_adder)
72{
73   if(DST_ADDER__ENABLE)
74   {
75      set_output(0,  DST_ADDER__IN0 + DST_ADDER__IN1 + DST_ADDER__IN2 + DST_ADDER__IN3);
76   }
77   else
78   {
79      set_output(0, 0);
80   }
81}
82
83
84/************************************************************************
85 *
86 * DST_COMP_ADDER  - Selectable parallel component adder
87 *
88 * input[0]    - Bit Select
89 *
90 * Also passed discrete_comp_adder_table structure
91 *
92 * Mar 2004, D Renaud.
93 ************************************************************************/
94#define DST_COMP_ADDER__SELECT  DISCRETE_INPUT(0)
95
96DISCRETE_STEP(dst_comp_adder)
97{
98   int select;
99
100   select = (int)DST_COMP_ADDER__SELECT;
101   assert(select < 256);
102   set_output(0,  m_total[select]);
103}
104
105DISCRETE_RESET(dst_comp_adder)
106{
107   DISCRETE_DECLARE_INFO(discrete_comp_adder_table)
108
109   int i, bit;
110   int bit_length = info->length;
111
112   assert(bit_length <= 8);
113
114   /* pre-calculate all possible values to speed up step routine */
115   for(i = 0; i < 256; i++)
116   {
117      switch (info->type)
118      {
119         case DISC_COMP_P_CAPACITOR:
120            m_total[i] = info->cDefault;
121            for(bit = 0; bit < bit_length; bit++)
122            {
123               if (i & (1 << bit))
124                  m_total[i] += info->c[bit];
125            }
126            break;
127         case DISC_COMP_P_RESISTOR:
128            m_total[i] = (info->cDefault != 0) ? 1.0 / info->cDefault : 0;
129            for(bit = 0; bit < bit_length; bit++)
130            {
131               if ((i & (1 << bit)) && (info->c[bit] != 0))
132                  m_total[i] += 1.0 / info->c[bit];
133            }
134            if (m_total[i] != 0)
135               m_total[i] = 1.0 / m_total[i];
136            break;
137      }
138   }
139   set_output(0,  m_total[0]);
140}
141
142/************************************************************************
143 *
144 * DST_CLAMP - Simple signal clamping circuit
145 *
146 * input[0]    - Input value
147 * input[1]    - Minimum value
148 * input[2]    - Maximum value
149 *
150 ************************************************************************/
151#define DST_CLAMP__IN       DISCRETE_INPUT(0)
152#define DST_CLAMP__MIN      DISCRETE_INPUT(1)
153#define DST_CLAMP__MAX      DISCRETE_INPUT(2)
154
155DISCRETE_STEP(dst_clamp)
156{
157   if (DST_CLAMP__IN < DST_CLAMP__MIN)
158      set_output(0,  DST_CLAMP__MIN);
159   else if (DST_CLAMP__IN > DST_CLAMP__MAX)
160      set_output(0,  DST_CLAMP__MAX);
161   else
162      set_output(0, DST_CLAMP__IN);
163}
164
165
166/************************************************************************
167 *
168 * DST_DAC_R1 - R1 Ladder DAC with cap smoothing
169 *
170 * input[0]    - Binary Data Input
171 * input[1]    - Data On Voltage (3.4 for TTL)
172 *
173 * also passed discrete_dac_r1_ladder structure
174 *
175 * Mar 2004, D Renaud.
176 * Nov 2010, D Renaud. - optimized for speed
177 ************************************************************************/
178#define DST_DAC_R1__DATA        DISCRETE_INPUT(0)
179#define DST_DAC_R1__VON         DISCRETE_INPUT(1)
180
181DISCRETE_STEP(dst_dac_r1)
182{
183   int     data = (int)DST_DAC_R1__DATA;
184   double  v = m_v_step[data];
185   double  x_time = DST_DAC_R1__DATA - data;
186   double  last_v = m_last_v;
187
188   m_last_v = v;
189
190   if (x_time > 0)
191      v = x_time * (v - last_v) + last_v;
192
193   /* Filter if needed, else just output voltage */
194   if (m_has_c_filter)
195   {
196      double v_diff = v - m_v_out;
197      /* optimization - if charged close enough to voltage */
198      if (fabs(v_diff) < 0.000001)
199         m_v_out = v;
200      else
201      {
202         m_v_out += v_diff * m_exponent;
203      }
204   }
205   else
206      m_v_out = v;
207
208   set_output(0, m_v_out);
209}
210
211DISCRETE_RESET(dst_dac_r1)
212{
213   DISCRETE_DECLARE_INFO(discrete_dac_r1_ladder)
214
215   int bit;
216   int ladderLength = info->ladderLength;
217   int total_steps = 1 << ladderLength;
218   double r_total = 0;
219   double i_bias;
220   double v_on = DST_DAC_R1__VON;
221
222   m_last_v = 0;
223
224   /* Calculate the Millman current of the bias circuit */
225   if (info->rBias > 0)
226      i_bias = info->vBias / info->rBias;
227   else
228      i_bias = 0;
229
230   /*
231    * We will do a small amount of error checking.
232    * But if you are an idiot and pass a bad ladder table
233    * then you deserve a crash.
234    */
235   if (ladderLength < 2 && info->rBias == 0 && info->rGnd == 0)
236   {
237      /* You need at least 2 resistors for a ladder */
238      m_device->discrete_log("dst_dac_r1_reset - Ladder length too small");
239   }
240   if (ladderLength > DISC_LADDER_MAXRES )
241   {
242      m_device->discrete_log("dst_dac_r1_reset - Ladder length exceeds DISC_LADDER_MAXRES");
243   }
244
245   /*
246    * Calculate the total of all resistors in parallel.
247    * This is the combined resistance of the voltage sources.
248    * This is used for the charging curve.
249    */
250   for(bit = 0; bit < ladderLength; bit++)
251   {
252      if (info->r[bit] > 0)
253         r_total += 1.0 / info->r[bit];
254   }
255   if (info->rBias > 0) r_total += 1.0 / info->rBias;
256   if (info->rGnd > 0)  r_total += 1.0 / info->rGnd;
257   r_total = 1.0 / r_total;
258
259   m_v_out = 0;
260
261   if (info->cFilter > 0)
262   {
263      m_has_c_filter = 1;
264      /* Setup filter constant */
265      m_exponent = RC_CHARGE_EXP(r_total * info->cFilter);
266   }
267   else
268      m_has_c_filter = 0;
269
270   /* pre-calculate all possible values to speed up step routine */
271   for(int i = 0; i < total_steps; i++)
272   {
273      double i_total = i_bias;
274      for (bit = 0; bit < ladderLength; bit++)
275      {
276         /* Add up currents of ON circuits per Millman. */
277
278         /* ignore if no resistor present */
279         if (EXPECTED(info->r[bit] > 0))
280         {
281            double i_bit;
282            int bit_val = (i >> bit) & 0x01;
283
284            if (bit_val != 0)
285               i_bit   = v_on / info->r[bit];
286            else
287               i_bit = 0;
288            i_total += i_bit;
289         }
290      }
291      m_v_step[i] = i_total * r_total;
292   }
293}
294
295
296/************************************************************************
297*
298 * DST_DIODE_MIX  - Diode Mixer
299 *
300 * input[0]    - Input 0
301 * .....
302 *
303 * Dec 2004, D Renaud.
304 ************************************************************************/
305#define DST_DIODE_MIX_INP_OFFSET    0
306#define DST_DIODE_MIX__INP(addr)    DISCRETE_INPUT(DST_DIODE_MIX_INP_OFFSET + addr)
307
308DISCRETE_STEP(dst_diode_mix)
309{
310   double  val, max = 0;
311   int     addr;
312
313   for (addr = 0; addr < m_size; addr++)
314   {
315      val = DST_DIODE_MIX__INP(addr) - m_v_junction[addr];
316      if (val > max) max = val;
317   }
318   if (max < 0) max = 0;
319   set_output(0,  max);
320}
321
322DISCRETE_RESET(dst_diode_mix)
323{
324   DISCRETE_DECLARE_INFO(double)
325
326   int     addr;
327
328   m_size = this->active_inputs() - DST_DIODE_MIX_INP_OFFSET;
329   assert(m_size <= 8);
330
331   for (addr = 0; addr < m_size; addr++)
332   {
333      if (info == NULL)
334      {
335         /* setup default junction voltage */
336         m_v_junction[addr] = 0.5;
337      }
338      else
339      {
340         /* use supplied junction voltage */
341         m_v_junction[addr] = *info++;
342      }
343   }
344   this->step();
345}
346
347
348/************************************************************************
349 *
350 * DST_DIVIDE  - Programmable divider with enable
351 *
352 * input[0]    - Enable input value
353 * input[1]    - Channel0 input value
354 * input[2]    - Divisor
355 *
356 ************************************************************************/
357#define DST_DIVIDE__ENABLE  DISCRETE_INPUT(0)
358#define DST_DIVIDE__IN      DISCRETE_INPUT(1)
359#define DST_DIVIDE__DIV     DISCRETE_INPUT(2)
360
361DISCRETE_STEP(dst_divide)
362{
363   if(DST_DIVIDE__ENABLE)
364   {
365      if(DST_DIVIDE__DIV == 0)
366      {
367         set_output(0, DBL_MAX); /* Max out but don't break */
368         m_device->discrete_log("dst_divider_step() - Divide by Zero attempted in NODE_%02d.\n",this->index());
369      }
370      else
371      {
372            set_output(0, DST_DIVIDE__IN / DST_DIVIDE__DIV);
373      }
374   }
375   else
376   {
377      set_output(0, 0);
378   }
379}
380
381
382/************************************************************************
383 *
384 * DST_GAIN - This is a programmable gain module with enable function
385 *
386 * input[0]    - Channel0 input value
387 * input[1]    - Gain value
388 * input[2]    - Final addition offset
389 *
390 ************************************************************************/
391#define DST_GAIN__IN        DISCRETE_INPUT(0)
392#define DST_GAIN__GAIN      DISCRETE_INPUT(1)
393#define DST_GAIN__OFFSET    DISCRETE_INPUT(2)
394
395DISCRETE_STEP(dst_gain)
396{
397      set_output(0, DST_GAIN__IN * DST_GAIN__GAIN + DST_GAIN__OFFSET);
398}
399
400
401/************************************************************************
402 *
403 * DST_INTEGRATE - Integration circuits
404 *
405 * input[0] - Trigger 0
406 * input[1] - Trigger 1
407 *
408 * also passed discrete_integrate_info structure
409 *
410 * Mar 2004, D Renaud.
411 ************************************************************************/
412#define DST_INTEGRATE__TRG0 DISCRETE_INPUT(0)
413#define DST_INTEGRATE__TRG1 DISCRETE_INPUT(1)
414
415static int dst_trigger_function(int trig0, int trig1, int trig2, int function)
416{
417   int result = 1;
418   switch (function)
419   {
420      case DISC_OP_AMP_TRIGGER_FUNCTION_TRG0:
421         result = trig0;
422         break;
423      case DISC_OP_AMP_TRIGGER_FUNCTION_TRG0_INV:
424         result = !trig0;
425         break;
426      case DISC_OP_AMP_TRIGGER_FUNCTION_TRG1:
427         result = trig1;
428         break;
429      case DISC_OP_AMP_TRIGGER_FUNCTION_TRG1_INV:
430         result = !trig1;
431         break;
432      case DISC_OP_AMP_TRIGGER_FUNCTION_TRG2:
433         result = trig2;
434         break;
435      case DISC_OP_AMP_TRIGGER_FUNCTION_TRG2_INV:
436         result = !trig2;
437         break;
438      case DISC_OP_AMP_TRIGGER_FUNCTION_TRG01_AND:
439         result = trig0 && trig1;
440         break;
441      case DISC_OP_AMP_TRIGGER_FUNCTION_TRG01_NAND:
442         result = !(trig0 && trig1);
443         break;
444   }
445
446   return (result);
447}
448
449DISCRETE_STEP(dst_integrate)
450{
451   DISCRETE_DECLARE_INFO(discrete_integrate_info)
452
453   int     trig0, trig1;
454   double  i_neg = 0;  /* current into - input */
455   double  i_pos = 0;  /* current into + input */
456
457   switch (info->type)
458   {
459      case DISC_INTEGRATE_OP_AMP_1:
460         if (DST_INTEGRATE__TRG0 != 0)
461         {
462            /* This forces the cap to completely charge,
463             * and the output to go to it's max value.
464             */
465            m_v_out = m_v_max_out;
466            set_output(0, m_v_out);
467            return;
468         }
469         m_v_out -= m_change;
470         break;
471
472      case DISC_INTEGRATE_OP_AMP_1 | DISC_OP_AMP_IS_NORTON:
473         i_neg = m_v_max_in / info->r1;
474         i_pos = (DST_INTEGRATE__TRG0 - OP_AMP_NORTON_VBE) / info->r2;
475         if (i_pos < 0) i_pos = 0;
476         m_v_out += (i_pos - i_neg) / this->sample_rate() / info->c;
477         break;
478
479      case DISC_INTEGRATE_OP_AMP_2 | DISC_OP_AMP_IS_NORTON:
480         trig0  = (int)DST_INTEGRATE__TRG0;
481         trig1  = (int)DST_INTEGRATE__TRG1;
482         i_neg  = dst_trigger_function(trig0, trig1, 0, info->f0) ? m_v_max_in_d / info->r1 : 0;
483         i_pos  = dst_trigger_function(trig0, trig1, 0, info->f1) ? m_v_max_in / info->r2 : 0;
484         i_pos += dst_trigger_function(trig0, trig1, 0, info->f2) ? m_v_max_in_d / info->r3 : 0;
485         m_v_out += (i_pos - i_neg) / this->sample_rate() / info->c;
486         break;
487   }
488
489   /* Clip the output. */
490   if (m_v_out < 0) m_v_out = 0;
491   if (m_v_out > m_v_max_out) m_v_out = m_v_max_out;
492
493   set_output(0, m_v_out);
494}
495
496DISCRETE_RESET(dst_integrate)
497{
498   DISCRETE_DECLARE_INFO(discrete_integrate_info)
499
500   double  i, v;
501
502   if (info->type & DISC_OP_AMP_IS_NORTON)
503   {
504      m_v_max_out  = info->vP - OP_AMP_NORTON_VBE;
505      m_v_max_in   = info->v1 - OP_AMP_NORTON_VBE;
506      m_v_max_in_d = m_v_max_in - OP_AMP_NORTON_VBE;
507   }
508   else
509   {
510      m_v_max_out =  info->vP - OP_AMP_VP_RAIL_OFFSET;
511
512      v = info->v1 * info->r3 / (info->r2 + info->r3);    /* vRef */
513      v = info->v1 - v;   /* actual charging voltage */
514      i = v / info->r1;
515      m_change = i / this->sample_rate() / info->c;
516   }
517   m_v_out = 0;
518   set_output(0, m_v_out);
519}
520
521
522/************************************************************************
523 *
524 * DST_LOGIC_INV - Logic invertor gate implementation
525 *
526 * input[0]    - Enable
527 * input[1]    - input[0] value
528 *
529 ************************************************************************/
530#define DST_LOGIC_INV__IN       DISCRETE_INPUT(0)
531
532DISCRETE_STEP(dst_logic_inv)
533{
534   set_output(0,  DST_LOGIC_INV__IN ? 0.0 : 1.0);
535}
536
537/************************************************************************
538 *
539 * DST_BITS_DECODE - Decode Bits from input node
540 *
541 ************************************************************************/
542#define DST_BITS_DECODE__IN     DISCRETE_INPUT(0)
543#define DST_BITS_DECODE__FROM   DISCRETE_INPUT(1)
544#define DST_BITS_DECODE__TO     DISCRETE_INPUT(2)
545#define DST_BITS_DECODE__VOUT   DISCRETE_INPUT(3)
546
547DISCRETE_STEP(dst_bits_decode)
548{
549   int new_val = DST_BITS_DECODE__IN;
550   int last_val = m_last_val;
551   int last_had_x_time = m_last_had_x_time;
552
553   if (last_val != new_val || last_had_x_time)
554   {
555      int i, new_bit, last_bit, last_bit_had_x_time, bit_changed;
556      double x_time = DST_BITS_DECODE__IN - new_val;
557      int from = m_from;
558      int count = m_count;
559      int decode_x_time = m_decode_x_time;
560      int has_x_time = x_time > 0 ? 1 : 0;
561      double out = 0;
562      double v_out = DST_BITS_DECODE__VOUT;
563
564      for (i = 0; i < count; i++ )
565      {
566         new_bit = (new_val >> (i + from)) & 1;
567         last_bit = (last_val >> (i + from)) & 1;
568         last_bit_had_x_time = (last_had_x_time >> (i + from)) & 1;
569         bit_changed = last_bit != new_bit ? 1 : 0;
570
571         if (!bit_changed && !last_bit_had_x_time)
572            continue;
573
574         if (decode_x_time)
575         {
576            out = new_bit;
577            if (bit_changed)
578               out += x_time;
579         }
580         else
581         {
582            out = v_out;
583            if (has_x_time && bit_changed)
584            {
585               if (new_bit)
586                  out *= x_time;
587               else
588                  out *= (1.0 - x_time);
589            }
590            else
591               out *= new_bit;
592         }
593         set_output(i, out);
594         if (has_x_time && bit_changed)
595            /* set */
596            m_last_had_x_time |= 1 << (i + from);
597         else
598            /* clear */
599            m_last_had_x_time &= ~(1 << (i + from));
600      }
601      m_last_val = new_val;
602   }
603}
604
605DISCRETE_RESET(dst_bits_decode)
606{
607   m_from = DST_BITS_DECODE__FROM;
608   m_count = DST_BITS_DECODE__TO - m_from + 1;
609   if (DST_BITS_DECODE__VOUT == 0)
610      m_decode_x_time = 1;
611   else
612      m_decode_x_time = 0;
613   m_last_had_x_time = 0;
614
615   this->step();
616}
617
618
619/************************************************************************
620 *
621 * DST_LOGIC_AND - Logic AND gate implementation
622 *
623 * input[0]    - input[0] value
624 * input[1]    - input[1] value
625 * input[2]    - input[2] value
626 * input[3]    - input[3] value
627 *
628 ************************************************************************/
629#define DST_LOGIC_AND__IN0      DISCRETE_INPUT(0)
630#define DST_LOGIC_AND__IN1      DISCRETE_INPUT(1)
631#define DST_LOGIC_AND__IN2      DISCRETE_INPUT(2)
632#define DST_LOGIC_AND__IN3      DISCRETE_INPUT(3)
633
634DISCRETE_STEP(dst_logic_and)
635{
636   set_output(0,  (DST_LOGIC_AND__IN0 && DST_LOGIC_AND__IN1 && DST_LOGIC_AND__IN2 && DST_LOGIC_AND__IN3)? 1.0 : 0.0);
637}
638
639/************************************************************************
640 *
641 * DST_LOGIC_NAND - Logic NAND gate implementation
642 *
643 * input[0]    - input[0] value
644 * input[1]    - input[1] value
645 * input[2]    - input[2] value
646 * input[3]    - input[3] value
647 *
648 ************************************************************************/
649#define DST_LOGIC_NAND__IN0     DISCRETE_INPUT(0)
650#define DST_LOGIC_NAND__IN1     DISCRETE_INPUT(1)
651#define DST_LOGIC_NAND__IN2     DISCRETE_INPUT(2)
652#define DST_LOGIC_NAND__IN3     DISCRETE_INPUT(3)
653
654DISCRETE_STEP(dst_logic_nand)
655{
656   set_output(0, (DST_LOGIC_NAND__IN0 && DST_LOGIC_NAND__IN1 && DST_LOGIC_NAND__IN2 && DST_LOGIC_NAND__IN3)? 0.0 : 1.0);
657}
658
659/************************************************************************
660 *
661 * DST_LOGIC_OR  - Logic OR  gate implementation
662 *
663 * input[0]    - input[0] value
664 * input[1]    - input[1] value
665 * input[2]    - input[2] value
666 * input[3]    - input[3] value
667 *
668 ************************************************************************/
669#define DST_LOGIC_OR__IN0       DISCRETE_INPUT(0)
670#define DST_LOGIC_OR__IN1       DISCRETE_INPUT(1)
671#define DST_LOGIC_OR__IN2       DISCRETE_INPUT(2)
672#define DST_LOGIC_OR__IN3       DISCRETE_INPUT(3)
673
674DISCRETE_STEP(dst_logic_or)
675{
676   set_output(0,  (DST_LOGIC_OR__IN0 || DST_LOGIC_OR__IN1 || DST_LOGIC_OR__IN2 || DST_LOGIC_OR__IN3) ? 1.0 : 0.0);
677}
678
679/************************************************************************
680 *
681 * DST_LOGIC_NOR - Logic NOR gate implementation
682 *
683 * input[0]    - input[0] value
684 * input[1]    - input[1] value
685 * input[2]    - input[2] value
686 * input[3]    - input[3] value
687 *
688 ************************************************************************/
689#define DST_LOGIC_NOR__IN0      DISCRETE_INPUT(0)
690#define DST_LOGIC_NOR__IN1      DISCRETE_INPUT(1)
691#define DST_LOGIC_NOR__IN2      DISCRETE_INPUT(2)
692#define DST_LOGIC_NOR__IN3      DISCRETE_INPUT(3)
693
694DISCRETE_STEP(dst_logic_nor)
695{
696   set_output(0,  (DST_LOGIC_NOR__IN0 || DST_LOGIC_NOR__IN1 || DST_LOGIC_NOR__IN2 || DST_LOGIC_NOR__IN3) ? 0.0 : 1.0);
697}
698
699/************************************************************************
700 *
701 * DST_LOGIC_XOR - Logic XOR gate implementation
702 *
703 * input[0]    - input[0] value
704 * input[1]    - input[1] value
705 *
706 ************************************************************************/
707#define DST_LOGIC_XOR__IN0      DISCRETE_INPUT(0)
708#define DST_LOGIC_XOR__IN1      DISCRETE_INPUT(1)
709
710DISCRETE_STEP(dst_logic_xor)
711{
712   set_output(0,  ((DST_LOGIC_XOR__IN0 && !DST_LOGIC_XOR__IN1) || (!DST_LOGIC_XOR__IN0 && DST_LOGIC_XOR__IN1)) ? 1.0 : 0.0);
713}
714
715/************************************************************************
716 *
717 * DST_LOGIC_NXOR - Logic NXOR gate implementation
718 *
719 * input[0]    - input[0] value
720 * input[1]    - input[1] value
721 *
722 ************************************************************************/
723#define DST_LOGIC_XNOR__IN0     DISCRETE_INPUT(0)
724#define DST_LOGIC_XNOR__IN1     DISCRETE_INPUT(1)
725
726DISCRETE_STEP(dst_logic_nxor)
727{
728   set_output(0,  ((DST_LOGIC_XNOR__IN0 && !DST_LOGIC_XNOR__IN1) || (!DST_LOGIC_XNOR__IN0 && DST_LOGIC_XNOR__IN1)) ? 0.0 : 1.0);
729}
730
731
732/************************************************************************
733 *
734 * DST_LOGIC_DFF - Standard D-type flip-flop implementation
735 *
736 * input[0]    - /Reset
737 * input[1]    - /Set
738 * input[2]    - clock
739 * input[3]    - data
740 *
741 ************************************************************************/
742#define DST_LOGIC_DFF__RESET    !DISCRETE_INPUT(0)
743#define DST_LOGIC_DFF__SET      !DISCRETE_INPUT(1)
744#define DST_LOGIC_DFF__CLOCK     DISCRETE_INPUT(2)
745#define DST_LOGIC_DFF__DATA      DISCRETE_INPUT(3)
746
747DISCRETE_STEP(dst_logic_dff)
748{
749   int clk = (int)DST_LOGIC_DFF__CLOCK;
750
751   if (DST_LOGIC_DFF__RESET)
752      set_output(0,  0);
753   else if (DST_LOGIC_DFF__SET)
754      set_output(0,  1);
755   else if (!m_last_clk && clk)    /* low to high */
756      set_output(0,  DST_LOGIC_DFF__DATA);
757   m_last_clk = clk;
758}
759
760DISCRETE_RESET(dst_logic_dff)
761{
762   m_last_clk = 0;
763   set_output(0,  0);
764}
765
766
767/************************************************************************
768 *
769 * DST_LOGIC_JKFF - Standard JK-type flip-flop implementation
770 *
771 * input[0]    - /Reset
772 * input[1]    - /Set
773 * input[2]    - clock
774 * input[3]    - J
775 * input[4]    - K
776 *
777 ************************************************************************/
778#define DST_LOGIC_JKFF__RESET   !DISCRETE_INPUT(0)
779#define DST_LOGIC_JKFF__SET     !DISCRETE_INPUT(1)
780#define DST_LOGIC_JKFF__CLOCK    DISCRETE_INPUT(2)
781#define DST_LOGIC_JKFF__J        DISCRETE_INPUT(3)
782#define DST_LOGIC_JKFF__K        DISCRETE_INPUT(4)
783
784DISCRETE_STEP(dst_logic_jkff)
785{
786   int clk = (int)DST_LOGIC_JKFF__CLOCK;
787   int j   = (int)DST_LOGIC_JKFF__J;
788   int k   = (int)DST_LOGIC_JKFF__K;
789
790   if (DST_LOGIC_JKFF__RESET)
791      m_v_out = 0;
792   else if (DST_LOGIC_JKFF__SET)
793      m_v_out = 1;
794   else if (m_last_clk && !clk)    /* high to low */
795   {
796      if (!j)
797      {
798         /* J=0, K=0 - Hold */
799         if (k)
800            /* J=0, K=1 - Reset */
801            m_v_out = 0;
802      }
803      else
804      {
805         if (!k)
806            /* J=1, K=0 - Set */
807            m_v_out = 1;
808         else
809            /* J=1, K=1 - Toggle */
810            m_v_out = !(int)m_v_out;
811      }
812   }
813   m_last_clk = clk;
814   set_output(0, m_v_out);
815}
816
817DISCRETE_RESET(dst_logic_jkff)
818{
819   m_last_clk = 0;
820   m_v_out = 0;
821   set_output(0, m_v_out);
822}
823
824/************************************************************************
825 *
826 * DST_LOGIC_SHIFT - Shift Register implementation
827 *
828 ************************************************************************/
829#define DST_LOGIC_SHIFT__IN         DISCRETE_INPUT(0)
830#define DST_LOGIC_SHIFT__RESET      DISCRETE_INPUT(1)
831#define DST_LOGIC_SHIFT__CLK        DISCRETE_INPUT(2)
832#define DST_LOGIC_SHIFT__SIZE       DISCRETE_INPUT(3)
833#define DST_LOGIC_SHIFT__OPTIONS    DISCRETE_INPUT(4)
834
835DISCRETE_STEP(dst_logic_shift)
836{
837   double  cycles;
838   double  ds_clock;
839   int     clock = 0, inc = 0;
840
841   int input_bit = (DST_LOGIC_SHIFT__IN != 0) ? 1 : 0;
842   ds_clock = DST_LOGIC_SHIFT__CLK;
843   if (m_clock_type == DISC_CLK_IS_FREQ)
844   {
845      /* We need to keep clocking the internal clock even if in reset. */
846      cycles = (m_t_left + this->sample_time()) * ds_clock;
847      inc    = (int)cycles;
848      m_t_left = (cycles - inc) / ds_clock;
849   }
850   else
851   {
852      clock  = (int)ds_clock;
853   }
854
855   /* If reset enabled then set output to the reset value.  No x_time in reset. */
856   if(((DST_LOGIC_SHIFT__RESET == 0) ? 0 : 1) == m_reset_on_high)
857   {
858      m_shift_data = 0;
859      set_output(0,  0);
860      return;
861   }
862
863   /* increment clock */
864   switch (m_clock_type)
865   {
866      case DISC_CLK_ON_F_EDGE:
867      case DISC_CLK_ON_R_EDGE:
868         /* See if the clock has toggled to the proper edge */
869         clock = (clock != 0);
870         if (m_last != clock)
871         {
872            m_last = clock;
873            if (m_clock_type == clock)
874            {
875               /* Toggled */
876               inc = 1;
877            }
878         }
879         break;
880
881      case DISC_CLK_BY_COUNT:
882         /* Clock number of times specified. */
883         inc = clock;
884         break;
885   }
886
887   if (inc > 0)
888   {
889      if (m_shift_r)
890      {
891         m_shift_data >>= 1;
892         m_shift_data |= input_bit << ((int)DST_LOGIC_SHIFT__SIZE - 1);
893         inc--;
894         m_shift_data >>= inc;
895      }
896      else
897      {
898         m_shift_data <<= 1;
899         m_shift_data |= input_bit;
900         inc--;
901         m_shift_data <<= inc;
902      }
903      m_shift_data &= m_bit_mask;
904   }
905
906   set_output(0,  m_shift_data);
907}
908
909DISCRETE_RESET(dst_logic_shift)
910{
911   m_bit_mask = (1 << (int)DST_LOGIC_SHIFT__SIZE) - 1;
912   m_clock_type = (int)DST_LOGIC_SHIFT__OPTIONS & DISC_CLK_MASK;
913   m_reset_on_high = ((int)DST_LOGIC_SHIFT__OPTIONS & DISC_LOGIC_SHIFT__RESET_H) ? 1 : 0;
914   m_shift_r = ((int)DST_LOGIC_SHIFT__OPTIONS & DISC_LOGIC_SHIFT__RIGHT)  ? 1 : 0;
915
916   m_t_left  = 0;
917   m_last = 0;
918   m_shift_data   = 0;
919   set_output(0, 0);
920}
921
922/************************************************************************
923 *
924 * DST_LOOKUP_TABLE  - Return value from lookup table
925 *
926 * input[0]    - Input 1
927 * input[1]    - Table size
928 *
929 * Also passed address of the lookup table
930 *
931 * Feb 2007, D Renaud.
932 ************************************************************************/
933#define DST_LOOKUP_TABLE__IN        DISCRETE_INPUT(0)
934#define DST_LOOKUP_TABLE__SIZE      DISCRETE_INPUT(1)
935
936DISCRETE_STEP(dst_lookup_table)
937{
938   DISCRETE_DECLARE_INFO(double)
939
940   int addr = DST_LOOKUP_TABLE__IN;
941
942   if (addr < 0 || addr >= DST_LOOKUP_TABLE__SIZE)
943      set_output(0,  0);
944   else
945      set_output(0,  info[addr]);
946}
947
948
949/************************************************************************
950 *
951 * DST_MIXER  - Mixer/Gain stage
952 *
953 * input[0]    - Enable input value
954 * input[1]    - Input 1
955 * input[2]    - Input 2
956 * input[3]    - Input 3
957 * input[4]    - Input 4
958 * input[5]    - Input 5
959 * input[6]    - Input 6
960 * input[7]    - Input 7
961 * input[8]    - Input 8
962 *
963 * Also passed discrete_mixer_info structure
964 *
965 * Mar 2004, D Renaud.
966 ************************************************************************/
967/*
968 * The input resistors can be a combination of static values and nodes.
969 * If a node is used then its value is in series with the static value.
970 * Also if a node is used and its value is 0, then that means the
971 * input is disconnected from the circuit.
972 *
973 * There are 3 basic types of mixers, defined by the 2 types.  The
974 * op amp mixer is further defined by the prescence of rI.  This is a
975 * brief explanation.
976 *
977 * DISC_MIXER_IS_RESISTOR
978 * The inputs are high pass filtered if needed, using (rX || rF) * cX.
979 * Then Millman is used for the voltages.
980 * r = (1/rF + 1/r1 + 1/r2...)
981 * i = (v1/r1 + v2/r2...)
982 * v = i * r
983 *
984 * DISC_MIXER_IS_OP_AMP - no rI
985 * This is just a summing circuit.
986 * The inputs are high pass filtered if needed, using rX * cX.
987 * Then a modified Millman is used for the voltages.
988 * i = ((vRef - v1)/r1 + (vRef - v2)/r2...)
989 * v = i * rF
990 *
991 * DISC_MIXER_IS_OP_AMP_WITH_RI
992 * The inputs are high pass filtered if needed, using (rX + rI) * cX.
993 * Then Millman is used for the voltages including vRef/rI.
994 * r = (1/rI + 1/r1 + 1/r2...)
995 * i = (vRef/rI + v1/r1 + v2/r2...)
996 * The voltage is then modified by an inverting amp formula.
997 * v = vRef + (rF/rI) * (vRef - (i * r))
998 */
999#define DST_MIXER__ENABLE       DISCRETE_INPUT(0)
1000#define DST_MIXER__IN(bit)      DISCRETE_INPUT(bit + 1)
1001
1002DISCRETE_STEP(dst_mixer)
1003{
1004   DISCRETE_DECLARE_INFO(discrete_mixer_desc)
1005
1006   double  v, vTemp, r_total, rTemp, rTemp2 = 0;
1007   double  i = 0;      /* total current of inputs */
1008   int     bit, connected;
1009
1010   /* put commonly used stuff in local variables for speed */
1011   int     r_node_bit_flag = m_r_node_bit_flag;
1012   int     c_bit_flag = m_c_bit_flag;
1013   int     bit_mask = 1;
1014   int     has_rF = (info->rF != 0);
1015   int     type = m_type;
1016   double  v_ref = info->vRef;
1017   double  rI = info->rI;
1018
1019   if (EXPECTED(DST_MIXER__ENABLE))
1020   {
1021      r_total = m_r_total;
1022
1023      if (UNEXPECTED(m_r_node_bit_flag != 0))
1024      {
1025         /* loop and do any high pass filtering for connected caps */
1026         /* but first see if there is an r_node for the current path */
1027         /* if so, then the exponents need to be re-calculated */
1028         for (bit = 0; bit < m_size; bit++)
1029         {
1030            rTemp     = info->r[bit];
1031            connected = 1;
1032            vTemp     = DST_MIXER__IN(bit);
1033
1034            /* is there a resistor? */
1035            if (r_node_bit_flag & bit_mask)
1036            {
1037               /* a node has the possibility of being disconnected from the circuit. */
1038               if (*m_r_node[bit] == 0)
1039                  connected = 0;
1040               else
1041               {
1042                  /* value currently holds resistance */
1043                  rTemp   += *m_r_node[bit];
1044                  r_total += 1.0 / rTemp;
1045                  /* is there a capacitor? */
1046                  if (c_bit_flag & bit_mask)
1047                  {
1048                     switch (type)
1049                     {
1050                        case DISC_MIXER_IS_RESISTOR:
1051                           /* is there an rF? */
1052                           if (has_rF)
1053                           {
1054                              rTemp2 = RES_2_PARALLEL(rTemp, info->rF);
1055                              break;
1056                           }
1057                           /* else, fall through and just use the resistor value */
1058                        case DISC_MIXER_IS_OP_AMP:
1059                           rTemp2 = rTemp;
1060                           break;
1061                        case DISC_MIXER_IS_OP_AMP_WITH_RI:
1062                           rTemp2 = rTemp + rI;
1063                           break;
1064                     }
1065                     /* Re-calculate exponent if resistor is a node and has changed value */
1066                     if (*m_r_node[bit] != m_r_last[bit])
1067                     {
1068                        m_exponent_rc[bit] =  RC_CHARGE_EXP(rTemp2 * info->c[bit]);
1069                        m_r_last[bit] = *m_r_node[bit];
1070                     }
1071                  }
1072               }
1073            }
1074
1075            if (connected)
1076            {
1077               /* is there a capacitor? */
1078               if (c_bit_flag & bit_mask)
1079               {
1080                  /* do input high pass filtering if needed. */
1081                  m_v_cap[bit] += (vTemp - v_ref - m_v_cap[bit]) * m_exponent_rc[bit];
1082                  vTemp -= m_v_cap[bit];
1083               }
1084               i += ((type == DISC_MIXER_IS_OP_AMP) ? v_ref - vTemp : vTemp) / rTemp;
1085            }
1086         bit_mask = bit_mask << 1;
1087         }
1088      }
1089      else if (UNEXPECTED(c_bit_flag != 0))
1090      {
1091         /* no r_nodes, so just do high pass filtering */
1092         for (bit = 0; bit < m_size; bit++)
1093         {
1094            vTemp = DST_MIXER__IN(bit);
1095
1096            if (c_bit_flag & (1 << bit))
1097            {
1098               /* do input high pass filtering if needed. */
1099               m_v_cap[bit] += (vTemp - v_ref - m_v_cap[bit]) * m_exponent_rc[bit];
1100               vTemp -= m_v_cap[bit];
1101            }
1102            i += ((type == DISC_MIXER_IS_OP_AMP) ? v_ref - vTemp : vTemp) / info->r[bit];
1103         }
1104      }
1105      else
1106      {
1107         /* no r_nodes or c_nodes, mixing only */
1108         if (UNEXPECTED(type == DISC_MIXER_IS_OP_AMP))
1109         {
1110            for (bit = 0; bit < m_size; bit++)
1111               i += ( v_ref - DST_MIXER__IN(bit) ) / info->r[bit];
1112         }
1113         else
1114         {
1115            for (bit = 0; bit < m_size; bit++)
1116               i += DST_MIXER__IN(bit) / info->r[bit];
1117         }
1118      }
1119
1120      if (UNEXPECTED(type == DISC_MIXER_IS_OP_AMP_WITH_RI))
1121         i += v_ref / rI;
1122
1123      r_total = 1.0 / r_total;
1124
1125      /* If resistor network or has rI then Millman is used.
1126       * If op-amp then summing formula is used. */
1127      v = i * ((type == DISC_MIXER_IS_OP_AMP) ? info->rF : r_total);
1128
1129      if (UNEXPECTED(type == DISC_MIXER_IS_OP_AMP_WITH_RI))
1130         v = v_ref + (m_gain * (v_ref - v));
1131
1132      /* Do the low pass filtering for cF */
1133      if (EXPECTED(info->cF != 0))
1134      {
1135         if (UNEXPECTED(r_node_bit_flag != 0))
1136         {
1137            /* Re-calculate exponent if resistor nodes are used */
1138            m_exponent_c_f =  RC_CHARGE_EXP(r_total * info->cF);
1139         }
1140         m_v_cap_f += (v - v_ref - m_v_cap_f) * m_exponent_c_f;
1141         v = m_v_cap_f;
1142      }
1143
1144      /* Do the high pass filtering for cAmp */
1145      if (EXPECTED(info->cAmp != 0))
1146      {
1147         m_v_cap_amp += (v - m_v_cap_amp) * m_exponent_c_amp;
1148         v -= m_v_cap_amp;
1149      }
1150      set_output(0,  v * info->gain);
1151   }
1152   else
1153   {
1154      set_output(0,  0);
1155   }
1156}
1157
1158
1159DISCRETE_RESET(dst_mixer)
1160{
1161   DISCRETE_DECLARE_INFO(discrete_mixer_desc)
1162
1163   int     bit;
1164   double  rTemp = 0;
1165
1166   /* link to r_node outputs */
1167   m_r_node_bit_flag = 0;
1168   for (bit = 0; bit < 8; bit++)
1169   {
1170      m_r_node[bit] = m_device->node_output_ptr(info->r_node[bit]);
1171      if (m_r_node[bit] != NULL)
1172      {
1173         m_r_node_bit_flag |= 1 << bit;
1174      }
1175
1176      /* flag any caps */
1177      if (info->c[bit] != 0)
1178         m_c_bit_flag |= 1 << bit;
1179   }
1180
1181   m_size = this->active_inputs() - 1;
1182
1183   /*
1184    * THERE IS NO ERROR CHECKING!!!!!!!!!
1185    * If you pass a bad ladder table
1186    * then you deserve a crash.
1187    */
1188
1189   m_type = info->type;
1190   if ((info->type == DISC_MIXER_IS_OP_AMP) && (info->rI != 0))
1191      m_type = DISC_MIXER_IS_OP_AMP_WITH_RI;
1192
1193   /*
1194    * Calculate the total of all resistors in parallel.
1195    * This is the combined resistance of the voltage sources.
1196    * Also calculate the exponents while we are here.
1197    */
1198   m_r_total = 0;
1199   for(bit = 0; bit < m_size; bit++)
1200   {
1201      if ((info->r[bit] != 0) && !info->r_node[bit] )
1202      {
1203         m_r_total += 1.0 / info->r[bit];
1204      }
1205
1206      m_v_cap[bit]       = 0;
1207      m_exponent_rc[bit] = 0;
1208      if ((info->c[bit] != 0)  && !info->r_node[bit])
1209      {
1210         switch (m_type)
1211         {
1212            case DISC_MIXER_IS_RESISTOR:
1213               /* is there an rF? */
1214               if (info->rF != 0)
1215               {
1216                  rTemp = 1.0 / ((1.0 / info->r[bit]) + (1.0 / info->rF));
1217                  break;
1218               }
1219               /* else, fall through and just use the resistor value */
1220            case DISC_MIXER_IS_OP_AMP:
1221               rTemp = info->r[bit];
1222               break;
1223            case DISC_MIXER_IS_OP_AMP_WITH_RI:
1224               rTemp = info->r[bit] + info->rI;
1225               break;
1226         }
1227         /* Setup filter constants */
1228         m_exponent_rc[bit] = RC_CHARGE_EXP(rTemp * info->c[bit]);
1229      }
1230   }
1231
1232   if (info->rF != 0)
1233   {
1234      if (m_type == DISC_MIXER_IS_RESISTOR) m_r_total += 1.0 / info->rF;
1235   }
1236   if (m_type == DISC_MIXER_IS_OP_AMP_WITH_RI) m_r_total += 1.0 / info->rI;
1237
1238   m_v_cap_f      = 0;
1239   m_exponent_c_f = 0;
1240   if (info->cF != 0)
1241   {
1242      /* Setup filter constants */
1243      m_exponent_c_f = RC_CHARGE_EXP(((info->type == DISC_MIXER_IS_OP_AMP) ? info->rF : (1.0 / m_r_total)) * info->cF);
1244   }
1245
1246   m_v_cap_amp      = 0;
1247   m_exponent_c_amp = 0;
1248   if (info->cAmp != 0)
1249   {
1250      /* Setup filter constants */
1251      /* We will use 100k ohms as an average final stage impedance. */
1252      /* Your amp/speaker system will have more effect on incorrect filtering then any value used here. */
1253      m_exponent_c_amp = RC_CHARGE_EXP(RES_K(100) * info->cAmp);
1254   }
1255
1256   if (m_type == DISC_MIXER_IS_OP_AMP_WITH_RI) m_gain = info->rF / info->rI;
1257
1258   set_output(0,  0);
1259}
1260
1261
1262/************************************************************************
1263 *
1264 * DST_MULTIPLEX - 1 of x multiplexer/switch
1265 *
1266 * input[0]    - switch position
1267 * input[1]    - input[0]
1268 * input[2]    - input[1]
1269 * .....
1270 *
1271 * Dec 2004, D Renaud.
1272 ************************************************************************/
1273#define DST_MULTIPLEX__ADDR         DISCRETE_INPUT(0)
1274#define DST_MULTIPLEX__INP(addr)    DISCRETE_INPUT(1 + addr)
1275
1276DISCRETE_STEP(dst_multiplex)
1277{
1278   int addr;
1279
1280   addr = DST_MULTIPLEX__ADDR; /* FP to INT */
1281   if ((addr >= 0) && (addr < m_size))
1282   {
1283      set_output(0,  DST_MULTIPLEX__INP(addr));
1284   }
1285   else
1286   {
1287      /* Bad address.  We will leave the output alone. */
1288      m_device->discrete_log("NODE_%02d - Address = %d. Out of bounds\n", this->index(), addr);
1289   }
1290}
1291
1292DISCRETE_RESET(dst_multiplex)
1293{
1294   m_size = this->active_inputs() - 1;
1295
1296   this->step();
1297}
1298
1299
1300/************************************************************************
1301 *
1302 * DST_ONESHOT - Usage of node_description values for one shot pulse
1303 *
1304 * input[0]    - Reset value
1305 * input[1]    - Trigger value
1306 * input[2]    - Amplitude value
1307 * input[3]    - Width of oneshot pulse
1308 * input[4]    - type R/F edge, Retriggerable?
1309 *
1310 * Complete re-write Jan 2004, D Renaud.
1311 ************************************************************************/
1312#define DST_ONESHOT__RESET  DISCRETE_INPUT(0)
1313#define DST_ONESHOT__TRIG   DISCRETE_INPUT(1)
1314#define DST_ONESHOT__AMP    DISCRETE_INPUT(2)
1315#define DST_ONESHOT__WIDTH  DISCRETE_INPUT(3)
1316#define DST_ONESHOT__TYPE   (int)DISCRETE_INPUT(4)
1317
1318DISCRETE_STEP(dst_oneshot)
1319{
1320   int trigger = (DST_ONESHOT__TRIG != 0);
1321
1322   /* If the state is triggered we will need to countdown later */
1323   int do_count = m_state;
1324
1325   if (UNEXPECTED(DST_ONESHOT__RESET))
1326   {
1327      /* Hold in Reset */
1328      set_output(0, 0);
1329      m_state  = 0;
1330   }
1331   else
1332   {
1333      /* are we at an edge? */
1334      if (UNEXPECTED(trigger != m_last_trig))
1335      {
1336         /* There has been a trigger edge */
1337         m_last_trig = trigger;
1338
1339         /* Is it the proper edge trigger */
1340         if ((m_type & DISC_ONESHOT_REDGE) ? trigger : !trigger)
1341         {
1342            if (!m_state)
1343            {
1344               /* We have first trigger */
1345               m_state     = 1;
1346               set_output(0, (m_type & DISC_OUT_ACTIVE_LOW) ? 0 : DST_ONESHOT__AMP);
1347               m_countdown = DST_ONESHOT__WIDTH;
1348            }
1349            else
1350            {
1351               /* See if we retrigger */
1352               if (m_type & DISC_ONESHOT_RETRIG)
1353               {
1354                  /* Retrigger */
1355                  m_countdown = DST_ONESHOT__WIDTH;
1356                  do_count = 0;
1357               }
1358            }
1359         }
1360      }
1361
1362      if (UNEXPECTED(do_count))
1363      {
1364         m_countdown -= this->sample_time();
1365         if(m_countdown <= 0.0)
1366         {
1367            set_output(0, (m_type & DISC_OUT_ACTIVE_LOW) ? DST_ONESHOT__AMP : 0);
1368            m_countdown = 0;
1369            m_state     = 0;
1370         }
1371      }
1372   }
1373}
1374
1375
1376DISCRETE_RESET(dst_oneshot)
1377{
1378   m_countdown = 0;
1379   m_state     = 0;
1380
1381   m_last_trig = 0;
1382   m_type = DST_ONESHOT__TYPE;
1383
1384   set_output(0,  (m_type & DISC_OUT_ACTIVE_LOW) ? DST_ONESHOT__AMP : 0);
1385}
1386
1387
1388/************************************************************************
1389 *
1390 * DST_RAMP - Ramp up/down model usage
1391 *
1392 * input[0]    - Enable ramp
1393 * input[1]    - Ramp Reverse/Forward switch
1394 * input[2]    - Gradient, change/sec
1395 * input[3]    - Start value
1396 * input[4]    - End value
1397 * input[5]    - Clamp value when disabled
1398 *
1399 ************************************************************************/
1400#define DST_RAMP__ENABLE    DISCRETE_INPUT(0)
1401#define DST_RAMP__DIR       DISCRETE_INPUT(1)
1402#define DST_RAMP__GRAD      DISCRETE_INPUT(2)
1403#define DST_RAMP__START     DISCRETE_INPUT(3)
1404#define DST_RAMP__END       DISCRETE_INPUT(4)
1405#define DST_RAMP__CLAMP     DISCRETE_INPUT(5)
1406
1407DISCRETE_STEP(dst_ramp)
1408{
1409   if(DST_RAMP__ENABLE)
1410   {
1411      if (!m_last_en)
1412      {
1413         m_last_en = 1;
1414         m_v_out = DST_RAMP__START;
1415      }
1416      if(m_dir ? DST_RAMP__DIR : !DST_RAMP__DIR) m_v_out += m_step;
1417      else m_v_out -= m_step;
1418      /* Clamp to min/max */
1419      if(m_dir ? (m_v_out < DST_RAMP__START)
1420            : (m_v_out > DST_RAMP__START)) m_v_out = DST_RAMP__START;
1421      if(m_dir ? (m_v_out > DST_RAMP__END)
1422            : (m_v_out < DST_RAMP__END)) m_v_out = DST_RAMP__END;
1423   }
1424   else
1425   {
1426      m_last_en = 0;
1427      /* Disabled so clamp to output */
1428      m_v_out = DST_RAMP__CLAMP;
1429   }
1430
1431   set_output(0, m_v_out);
1432}
1433
1434DISCRETE_RESET(dst_ramp)
1435{
1436   m_v_out = DST_RAMP__CLAMP;
1437   m_step    = DST_RAMP__GRAD / this->sample_rate();
1438   m_dir     = ((DST_RAMP__END - DST_RAMP__START) == abs(DST_RAMP__END - DST_RAMP__START));
1439   m_last_en = 0;
1440}
1441
1442
1443/************************************************************************
1444 *
1445 * DST_SAMPHOLD - Sample & Hold Implementation
1446 *
1447 * input[0]    - input[0] value
1448 * input[1]    - clock node
1449 * input[2]    - clock type
1450 *
1451 ************************************************************************/
1452#define DST_SAMPHOLD__IN0       DISCRETE_INPUT(0)
1453#define DST_SAMPHOLD__CLOCK     DISCRETE_INPUT(1)
1454#define DST_SAMPHOLD__TYPE      DISCRETE_INPUT(2)
1455
1456DISCRETE_STEP(dst_samphold)
1457{
1458   switch(m_clocktype)
1459   {
1460      case DISC_SAMPHOLD_REDGE:
1461         /* Clock the whole time the input is rising */
1462         if (DST_SAMPHOLD__CLOCK > m_last_input) set_output(0,  DST_SAMPHOLD__IN0);
1463         break;
1464      case DISC_SAMPHOLD_FEDGE:
1465         /* Clock the whole time the input is falling */
1466         if(DST_SAMPHOLD__CLOCK < m_last_input) set_output(0,  DST_SAMPHOLD__IN0);
1467         break;
1468      case DISC_SAMPHOLD_HLATCH:
1469         /* Output follows input if clock != 0 */
1470         if( DST_SAMPHOLD__CLOCK) set_output(0,  DST_SAMPHOLD__IN0);
1471         break;
1472      case DISC_SAMPHOLD_LLATCH:
1473         /* Output follows input if clock == 0 */
1474         if (DST_SAMPHOLD__CLOCK == 0) set_output(0,  DST_SAMPHOLD__IN0);
1475         break;
1476      default:
1477         m_device->discrete_log("dst_samphold_step - Invalid clocktype passed");
1478         break;
1479   }
1480   /* Save the last value */
1481   m_last_input = DST_SAMPHOLD__CLOCK;
1482}
1483
1484DISCRETE_RESET(dst_samphold)
1485{
1486   set_output(0, 0);
1487   m_last_input = -1;
1488   /* Only stored in here to speed up and save casting in the step function */
1489   m_clocktype = (int)DST_SAMPHOLD__TYPE;
1490   this->step();
1491}
1492
1493
1494/************************************************************************
1495 *
1496 * DST_SWITCH - Programmable 2 pole switch module with enable function
1497 *
1498 * input[0]    - Enable input value
1499 * input[1]    - switch position
1500 * input[2]    - input[0]
1501 * input[3]    - input[1]
1502 *
1503 ************************************************************************/
1504#define DST_SWITCH__ENABLE  DISCRETE_INPUT(0)
1505#define DST_SWITCH__SWITCH  DISCRETE_INPUT(1)
1506#define DST_SWITCH__IN0     DISCRETE_INPUT(2)
1507#define DST_SWITCH__IN1     DISCRETE_INPUT(3)
1508
1509DISCRETE_STEP(dst_switch)
1510{
1511   if(DST_SWITCH__ENABLE)
1512   {
1513      set_output(0,  DST_SWITCH__SWITCH ? DST_SWITCH__IN1 : DST_SWITCH__IN0);
1514   }
1515   else
1516   {
1517      set_output(0,  0);
1518   }
1519}
1520
1521/************************************************************************
1522 *
1523 * DST_ASWITCH - Analog switch
1524 *
1525 * input[1]    - Control
1526 * input[2]    - Input
1527 * input[3]    - Threshold for enable
1528 *
1529 ************************************************************************/
1530#define DST_ASWITCH__CTRL       DISCRETE_INPUT(0)
1531#define DST_ASWITCH__IN         DISCRETE_INPUT(1)
1532#define DST_ASWITCH__THRESHOLD  DISCRETE_INPUT(2)
1533
1534
1535DISCRETE_STEP(dst_aswitch)
1536{
1537   set_output(0,  DST_ASWITCH__CTRL > DST_ASWITCH__THRESHOLD ? DST_ASWITCH__IN : 0);
1538}
1539
1540/************************************************************************
1541 *
1542 * DST_TRANSFORM - Programmable math module
1543 *
1544 * input[0]    - Channel0 input value
1545 * input[1]    - Channel1 input value
1546 * input[2]    - Channel2 input value
1547 * input[3]    - Channel3 input value
1548 * input[4]    - Channel4 input value
1549 *
1550 ************************************************************************/
1551#define MAX_TRANS_STACK 16
1552
1553struct double_stack {
1554public:
1555   double_stack() : p(&stk[0])  { }
1556   inline void push(double v)
1557   {
1558      //Store THEN increment
1559      assert(p <= &stk[MAX_TRANS_STACK-1]);
1560      *p++ = v;
1561   }
1562   inline double pop(void)
1563   {
1564      //decrement THEN read
1565      assert(p > &stk[0]);
1566      p--;
1567      return *p;
1568   }
1569private:
1570   double stk[MAX_TRANS_STACK];
1571   double *p;
1572};
1573
1574DISCRETE_STEP(dst_transform)
1575{
1576   double_stack    stack;
1577   double  top;
1578
1579   enum token *fPTR = &precomp[0];
1580
1581   top = HUGE_VAL;
1582
1583   while(*fPTR != TOK_END)
1584   {
1585      switch (*fPTR++)
1586      {
1587         case TOK_MULT:      top = stack.pop() * top;                    break;
1588         case TOK_DIV:       top = stack.pop() / top;                    break;
1589         case TOK_ADD:       top = stack.pop() + top;                    break;
1590         case TOK_MINUS:     top = stack.pop() - top;                    break;
1591         case TOK_0:         stack.push(top); top = I_IN0();             break;
1592         case TOK_1:         stack.push(top); top = I_IN1();             break;
1593         case TOK_2:         stack.push(top); top = I_IN2();             break;
1594         case TOK_3:         stack.push(top); top = I_IN3();             break;
1595         case TOK_4:         stack.push(top); top = I_IN4();             break;
1596         case TOK_DUP:       stack.push(top);                            break;
1597         case TOK_ABS:       top = fabs(top);                            break;  /* absolute value */
1598         case TOK_NEG:       top = -top;                                 break;  /* * -1 */
1599         case TOK_NOT:       top = !top;                                 break;  /* Logical NOT of Last Value */
1600         case TOK_EQUAL:     top = (int)stack.pop() == (int)top;         break;  /* Logical = */
1601         case TOK_GREATER:   top = (stack.pop() > top);                  break;  /* Logical > */
1602         case TOK_LESS:      top = (stack.pop() < top);                  break;  /* Logical < */
1603         case TOK_AND:       top = (int)stack.pop() & (int)top;          break;  /* Bitwise AND */
1604         case TOK_OR:        top = (int)stack.pop() | (int)top;          break;  /* Bitwise OR */
1605         case TOK_XOR:       top = (int)stack.pop() ^ (int)top;          break;  /* Bitwise XOR */
1606         case TOK_END:       break; /* please compiler */
1607      }
1608   }
1609   set_output(0,  top);
1610}
1611
1612DISCRETE_RESET(dst_transform)
1613{
1614   const char *fPTR = (const char *)this->custom_data();
1615   enum token *p = &precomp[0];
1616
1617   while(*fPTR != 0)
1618   {
1619      switch (*fPTR++)
1620      {
1621         case '*':   *p = TOK_MULT;      break;
1622         case '/':   *p = TOK_DIV;       break;
1623         case '+':   *p = TOK_ADD;       break;
1624         case '-':   *p = TOK_MINUS;     break;
1625         case '0':   *p = TOK_0;         break;
1626         case '1':   *p = TOK_1;         break;
1627         case '2':   *p = TOK_2;         break;
1628         case '3':   *p = TOK_3;         break;
1629         case '4':   *p = TOK_4;         break;
1630         case 'P':   *p = TOK_DUP;       break;
1631         case 'a':   *p = TOK_ABS;       break; /* absolute value */
1632         case 'i':   *p = TOK_NEG;       break; /* * -1 */
1633         case '!':   *p = TOK_NOT;       break; /* Logical NOT of Last Value */
1634         case '=':   *p = TOK_EQUAL;     break; /* Logical = */
1635         case '>':   *p = TOK_GREATER;   break; /* Logical > */
1636         case '<':   *p = TOK_LESS;      break; /* Logical < */
1637         case '&':   *p = TOK_AND;       break; /* Bitwise AND */
1638         case '|':   *p = TOK_OR;        break; /* Bitwise OR */
1639         case '^':   *p = TOK_XOR;       break; /* Bitwise XOR */
1640         default:
1641            m_device->discrete_log("dst_transform_step - Invalid function type/variable passed: %s",(const char *)this->custom_data());
1642            /* that is enough to fatalerror */
1643            fatalerror("dst_transform_step - Invalid function type/variable passed: %s\n", (const char *)this->custom_data());
1644            break;
1645      }
1646      p++;
1647   }
1648   *p = TOK_END;
1649}
1650
1651/************************************************************************
1652 *
1653 * DST_OP_AMP - op amp circuits
1654 *
1655 * input[0] - Enable
1656 * input[1] - Input 0
1657 * input[2] - Input 1
1658 *
1659 * also passed discrete_op_amp_info structure
1660 *
1661 * Mar 2007, D Renaud.
1662 ************************************************************************/
1663#define DST_OP_AMP__ENABLE  DISCRETE_INPUT(0)
1664#define DST_OP_AMP__INP0    DISCRETE_INPUT(1)
1665#define DST_OP_AMP__INP1    DISCRETE_INPUT(2)
1666
1667DISCRETE_STEP(dst_op_amp)
1668{
1669   DISCRETE_DECLARE_INFO(discrete_op_amp_info)
1670
1671   double i_pos = 0;
1672   double i_neg = 0;
1673   double i    = 0;
1674   double v_out;
1675
1676   if (DST_OP_AMP__ENABLE)
1677   {
1678      switch (info->type)
1679      {
1680         case DISC_OP_AMP_IS_NORTON:
1681            /* work out neg pin current */
1682            if  (m_has_r1)
1683            {
1684               i_neg = (DST_OP_AMP__INP0 - OP_AMP_NORTON_VBE) / info->r1;
1685               if (i_neg < 0) i_neg = 0;
1686            }
1687            i_neg += m_i_fixed;
1688
1689            /* work out neg pin current */
1690            i_pos = (DST_OP_AMP__INP1 - OP_AMP_NORTON_VBE) / info->r2;
1691            if (i_pos < 0) i_pos = 0;
1692
1693            /* work out current across r4 */
1694            i = i_pos - i_neg;
1695
1696            if (m_has_cap)
1697            {
1698               if (m_has_r4)
1699               {
1700                  /* voltage across r4 charging cap */
1701                  i *= info->r4;
1702                  /* exponential charge */
1703                  m_v_cap += (i - m_v_cap) * m_exponent;
1704               }
1705               else
1706                  /* linear charge */
1707                  m_v_cap += i / m_exponent;
1708               v_out = m_v_cap;
1709            }
1710            else
1711               if (m_has_r4)
1712                  v_out = i * info->r4;
1713               else
1714                  /* output just swings to rail when there is no r4 */
1715                  if (i > 0)
1716                     v_out = m_v_max;
1717                  else
1718                     v_out = 0;
1719
1720            /* clamp output */
1721            if (v_out > m_v_max) v_out = m_v_max;
1722            else if (v_out < info->vN) v_out = info->vN;
1723            m_v_cap = v_out;
1724
1725            set_output(0, v_out);
1726            break;
1727
1728         default:
1729            set_output(0, 0);
1730      }
1731   }
1732   else
1733      set_output(0, 0);
1734}
1735
1736DISCRETE_RESET(dst_op_amp)
1737{
1738   DISCRETE_DECLARE_INFO(discrete_op_amp_info)
1739
1740   m_has_r1 = info->r1 > 0;
1741   m_has_r4 = info->r4 > 0;
1742
1743   m_v_max = info->vP - OP_AMP_NORTON_VBE;
1744
1745   m_v_cap = 0;
1746   if (info->c > 0)
1747   {
1748      m_has_cap = 1;
1749      /* Setup filter constants */
1750      if (m_has_r4)
1751      {
1752         /* exponential charge */
1753         m_exponent = RC_CHARGE_EXP(info->r4 * info->c);
1754      }
1755      else
1756         /* linear charge */
1757         m_exponent = this->sample_rate() * info->c;
1758   }
1759
1760   if (info->r3 > 0)
1761      m_i_fixed = (info->vP - OP_AMP_NORTON_VBE) / info->r3;
1762   else
1763      m_i_fixed = 0;
1764}
1765
1766
1767/************************************************************************
1768 *
1769 * DST_OP_AMP_1SHT - op amp one shot circuits
1770 *
1771 * input[0] - Trigger
1772 *
1773 * also passed discrete_op_amp_1sht_info structure
1774 *
1775 * Mar 2007, D Renaud.
1776 ************************************************************************/
1777#define DST_OP_AMP_1SHT__TRIGGER    DISCRETE_INPUT(0)
1778
1779DISCRETE_STEP(dst_op_amp_1sht)
1780{
1781   DISCRETE_DECLARE_INFO(discrete_op_amp_1sht_info)
1782
1783   double i_pos;
1784   double i_neg;
1785   double v;
1786
1787   /* update trigger circuit */
1788   i_pos  = (DST_OP_AMP_1SHT__TRIGGER - m_v_cap2) / info->r2;
1789   i_pos += m_v_out / info->r5;
1790   m_v_cap2 += (DST_OP_AMP_1SHT__TRIGGER - m_v_cap2) * m_exponent2;
1791
1792   /* calculate currents and output */
1793   i_neg = (m_v_cap1 - OP_AMP_NORTON_VBE) / info->r3;
1794   if (i_neg < 0) i_neg = 0;
1795   i_neg += m_i_fixed;
1796
1797   if (i_pos > i_neg) m_v_out = m_v_max;
1798   else m_v_out = info->vN;
1799
1800   /* update c1 */
1801   /* rough value of voltage at anode of diode if discharging */
1802   v = m_v_out + 0.6;
1803   if (m_v_cap1 > m_v_out)
1804   {
1805      /* discharge */
1806      if (m_v_cap1 > v)
1807         /* immediate discharge through diode */
1808         m_v_cap1 = v;
1809      else
1810         /* discharge through r4 */
1811         m_v_cap1 += (m_v_out - m_v_cap1) * m_exponent1d;
1812   }
1813   else
1814      /* charge */
1815      m_v_cap1 += ((m_v_out - OP_AMP_NORTON_VBE) * m_r34ratio + OP_AMP_NORTON_VBE - m_v_cap1) * m_exponent1c;
1816
1817   set_output(0, m_v_out);
1818}
1819
1820DISCRETE_RESET(dst_op_amp_1sht)
1821{
1822   DISCRETE_DECLARE_INFO(discrete_op_amp_1sht_info)
1823
1824   m_exponent1c = RC_CHARGE_EXP(RES_2_PARALLEL(info->r3, info->r4) * info->c1);
1825   m_exponent1d = RC_CHARGE_EXP(info->r4 * info->c1);
1826   m_exponent2  = RC_CHARGE_EXP(info->r2 * info->c2);
1827   m_i_fixed  = (info->vP - OP_AMP_NORTON_VBE) / info->r1;
1828   m_v_cap1   = m_v_cap2 = 0;
1829   m_v_max    = info->vP - OP_AMP_NORTON_VBE;
1830   m_r34ratio = info->r3 / (info->r3 + info->r4);
1831}
1832
1833
1834/************************************************************************
1835 *
1836 * DST_TVCA_OP_AMP - trigged op-amp VCA
1837 *
1838 * input[0] - Trigger 0
1839 * input[1] - Trigger 1
1840 * input[2] - Trigger 2
1841 * input[3] - Input 0
1842 * input[4] - Input 1
1843 *
1844 * also passed discrete_op_amp_tvca_info structure
1845 *
1846 * Mar 2004, D Renaud.
1847 ************************************************************************/
1848#define DST_TVCA_OP_AMP__TRG0   DISCRETE_INPUT(0)
1849#define DST_TVCA_OP_AMP__TRG1   DISCRETE_INPUT(1)
1850#define DST_TVCA_OP_AMP__TRG2   DISCRETE_INPUT(2)
1851#define DST_TVCA_OP_AMP__INP0   DISCRETE_INPUT(3)
1852#define DST_TVCA_OP_AMP__INP1   DISCRETE_INPUT(4)
1853
1854DISCRETE_STEP(dst_tvca_op_amp)
1855{
1856   DISCRETE_DECLARE_INFO(discrete_op_amp_tvca_info)
1857
1858   int     trig0, trig1, trig2, f3;
1859   double  i2 = 0;     /* current through r2 */
1860   double  i3 = 0;     /* current through r3 */
1861   double  i_neg = 0;  /* current into - input */
1862   double  i_pos = 0;  /* current into + input */
1863   double  i_out = 0;  /* current at output */
1864
1865   double  v_out;
1866
1867   trig0 = (int)DST_TVCA_OP_AMP__TRG0;
1868   trig1 = (int)DST_TVCA_OP_AMP__TRG1;
1869   trig2 = (int)DST_TVCA_OP_AMP__TRG2;
1870   f3 = dst_trigger_function(trig0, trig1, trig2, info->f3);
1871
1872   if ((info->r2 != 0) && dst_trigger_function(trig0, trig1, trig2, info->f0))
1873      {
1874         /* r2 is present, so we assume Input 0 is connected and valid. */
1875         i2 = (DST_TVCA_OP_AMP__INP0 - OP_AMP_NORTON_VBE) / info->r2;
1876         if ( i2 < 0) i2 = 0;
1877      }
1878
1879   if ((info->r3 != 0) && dst_trigger_function(trig0, trig1, trig2, info->f1))
1880      {
1881         /* r2 is present, so we assume Input 1 is connected and valid. */
1882         /* Function F1 is not grounding the circuit. */
1883         i3 = (DST_TVCA_OP_AMP__INP1 - OP_AMP_NORTON_VBE) / info->r3;
1884         if ( i3 < 0) i3 = 0;
1885      }
1886
1887   /* Calculate current going in to - input. */
1888   i_neg = m_i_fixed + i2 + i3;
1889
1890   /* Update the c1 cap voltage. */
1891   if (dst_trigger_function(trig0, trig1, trig2, info->f2))
1892   {
1893      /* F2 is not grounding the circuit so we charge the cap. */
1894      m_v_cap1 += (m_v_trig[f3] - m_v_cap1) * m_exponent_c[f3];
1895   }
1896   else
1897   {
1898      /* F2 is at ground.  The diode blocks this so F2 and r5 are out of circuit.
1899       * So now the discharge rate is dependent upon F3.
1900       * If F3 is at ground then we discharge to 0V through r6.
1901       * If F3 is out of circuit then we discharge to OP_AMP_NORTON_VBE through r6+r7. */
1902      m_v_cap1 += ((f3 ? OP_AMP_NORTON_VBE : 0.0) - m_v_cap1) * m_exponent_d[f3];
1903   }
1904
1905   /* Calculate c1 current going in to + input. */
1906   i_pos = (m_v_cap1 - OP_AMP_NORTON_VBE) / m_r67;
1907   if ((i_pos < 0) || !f3) i_pos = 0;
1908
1909   /* Update the c2 cap voltage and current. */
1910   if (info->r9 != 0)
1911   {
1912      f3 = dst_trigger_function(trig0, trig1, trig2, info->f4);
1913      m_v_cap2 += ((f3 ? m_v_trig2 : 0) - m_v_cap2) * m_exponent2[f3];
1914      i_pos += m_v_cap2 / info->r9;
1915   }
1916
1917   /* Update the c3 cap voltage and current. */
1918   if (info->r11 != 0)
1919   {
1920      f3 = dst_trigger_function(trig0, trig1, trig2, info->f5);
1921      m_v_cap3 += ((f3 ? m_v_trig3 : 0) - m_v_cap3) * m_exponent3[f3];
1922      i_pos += m_v_cap3 / info->r11;
1923   }
1924
1925   /* Calculate output current. */
1926   i_out = i_pos - i_neg;
1927   if (i_out < 0) i_out = 0;
1928
1929   /* Convert to voltage for final output. */
1930   if (m_has_c4)
1931   {
1932      if (m_has_r4)
1933      {
1934         /* voltage across r4 charging cap */
1935         i_out *= info->r4;
1936         /* exponential charge */
1937         m_v_cap4 += (i_out - m_v_cap4) * m_exponent4;
1938      }
1939      else
1940      /* linear charge */
1941         m_v_cap4 += i_out / m_exponent4;
1942      if (m_v_cap4 < 0)
1943         m_v_cap4 = 0;
1944      v_out = m_v_cap4;
1945   }
1946   else
1947      v_out = i_out * info->r4;
1948
1949
1950
1951   /* Clip the output if needed. */
1952   if (v_out > m_v_out_max) v_out = m_v_out_max;
1953
1954   set_output(0, v_out);
1955}
1956
1957DISCRETE_RESET(dst_tvca_op_amp)
1958{
1959   DISCRETE_DECLARE_INFO(discrete_op_amp_tvca_info)
1960
1961   m_r67 = info->r6 + info->r7;
1962
1963   m_v_out_max = info->vP - OP_AMP_NORTON_VBE;
1964   /* This is probably overkill because R5 is usually much lower then r6 or r7,
1965    * but it is better to play it safe. */
1966   m_v_trig[0] = (info->v1 - 0.6) * RES_VOLTAGE_DIVIDER(info->r5, info->r6);
1967   m_v_trig[1] = (info->v1 - 0.6 - OP_AMP_NORTON_VBE) * RES_VOLTAGE_DIVIDER(info->r5, m_r67) + OP_AMP_NORTON_VBE;
1968   m_i_fixed   = m_v_out_max / info->r1;
1969
1970   m_v_cap1 = 0;
1971   /* Charge rate through r5 */
1972   /* There can be a different charge rates depending on function F3. */
1973   m_exponent_c[0] = RC_CHARGE_EXP(RES_2_PARALLEL(info->r5, info->r6) * info->c1);
1974   m_exponent_c[1] = RC_CHARGE_EXP(RES_2_PARALLEL(info->r5, m_r67) * info->c1);
1975   /* Discharge rate through r6 + r7 */
1976   m_exponent_d[1] = RC_CHARGE_EXP(m_r67 * info->c1);
1977   /* Discharge rate through r6 */
1978   if (info->r6 != 0)
1979   {
1980      m_exponent_d[0] = RC_CHARGE_EXP(info->r6 * info->c1);
1981   }
1982   m_v_cap2       = 0;
1983   m_v_trig2      = (info->v2 - 0.6 - OP_AMP_NORTON_VBE) * RES_VOLTAGE_DIVIDER(info->r8, info->r9);
1984   m_exponent2[0] = RC_CHARGE_EXP(info->r9 * info->c2);
1985   m_exponent2[1] = RC_CHARGE_EXP(RES_2_PARALLEL(info->r8, info->r9) * info->c2);
1986   m_v_cap3       = 0;
1987   m_v_trig3      = (info->v3 - 0.6 - OP_AMP_NORTON_VBE) * RES_VOLTAGE_DIVIDER(info->r10, info->r11);
1988   m_exponent3[0] = RC_CHARGE_EXP(info->r11 * info->c3);
1989   m_exponent3[1] = RC_CHARGE_EXP(RES_2_PARALLEL(info->r10, info->r11) * info->c3);
1990   m_v_cap4       = 0;
1991   if (info->r4 != 0) m_has_r4 = 1;
1992   if (info->c4 != 0) m_has_c4 = 1;
1993   if (m_has_r4 && m_has_c4)
1994      m_exponent4    = RC_CHARGE_EXP(info->r4 * info->c4);
1995
1996   this->step();
1997}
1998
1999
2000/* the different logic and xtime states */
2001enum
2002{
2003   XTIME__IN0_0__IN1_0__IN0_NOX__IN1_NOX = 0,
2004   XTIME__IN0_0__IN1_0__IN0_NOX__IN1_X,
2005   XTIME__IN0_0__IN1_0__IN0_X__IN1_NOX,
2006   XTIME__IN0_0__IN1_0__IN0_X__IN1_X,
2007   XTIME__IN0_0__IN1_1__IN0_NOX__IN1_NOX,
2008   XTIME__IN0_0__IN1_1__IN0_NOX__IN1_X,
2009   XTIME__IN0_0__IN1_1__IN0_X__IN1_NOX,
2010   XTIME__IN0_0__IN1_1__IN0_X__IN1_X,
2011   XTIME__IN0_1__IN1_0__IN0_NOX__IN1_NOX,
2012   XTIME__IN0_1__IN1_0__IN0_NOX__IN1_X,
2013   XTIME__IN0_1__IN1_0__IN0_X__IN1_NOX,
2014   XTIME__IN0_1__IN1_0__IN0_X__IN1_X,
2015   XTIME__IN0_1__IN1_1__IN0_NOX__IN1_NOX,
2016   XTIME__IN0_1__IN1_1__IN0_NOX__IN1_X,
2017   XTIME__IN0_1__IN1_1__IN0_X__IN1_NOX,
2018   XTIME__IN0_1__IN1_1__IN0_X__IN1_X
2019};
2020
2021
2022/************************************************************************
2023 *
2024 * DST_XTIME_BUFFER - Buffer/Invertor gate implementation using X_TIME
2025 *
2026 * If OUT_LOW and OUT_HIGH are defined then the output will be energy.
2027 * If they are both 0, then the output will be X_TIME logic.
2028 *
2029 ************************************************************************/
2030#define DST_XTIME_BUFFER__IN            DISCRETE_INPUT(0)
2031#define DST_XTIME_BUFFER_OUT_LOW        DISCRETE_INPUT(1)
2032#define DST_XTIME_BUFFER_OUT_HIGH       DISCRETE_INPUT(2)
2033#define DST_XTIME_BUFFER_INVERT         DISCRETE_INPUT(3)
2034
2035DISCRETE_STEP(dst_xtime_buffer)
2036{
2037   int in0 = (int)DST_XTIME_BUFFER__IN;
2038   int out = in0;
2039   int out_is_energy = 1;
2040
2041   double x_time = DST_XTIME_BUFFER__IN - in0;
2042
2043   double out_low = DST_XTIME_BUFFER_OUT_LOW;
2044   double out_high = DST_XTIME_BUFFER_OUT_HIGH;
2045
2046   if (out_low ==0 && out_high == 0)
2047      out_is_energy = 0;
2048
2049   if (DST_XTIME_BUFFER_INVERT != 0)
2050      out ^= 1;
2051
2052   if (out_is_energy)
2053   {
2054      if (x_time > 0)
2055      {
2056         double diff = out_high - out_low;
2057         diff = out ? diff * x_time : diff * (1.0 - x_time);
2058         set_output(0,  out_low + diff);
2059      }
2060      else
2061         set_output(0,  out ? out_high : out_low);
2062   }
2063   else
2064      set_output(0,  out + x_time);
2065}
2066
2067
2068/************************************************************************
2069 *
2070 * DST_XTIME_AND - AND/NAND gate implementation using X_TIME
2071 *
2072 * If OUT_LOW and OUT_HIGH are defined then the output will be energy.
2073 * If they are both 0, then the output will be X_TIME logic.
2074 *
2075 ************************************************************************/
2076#define DST_XTIME_AND__IN0          DISCRETE_INPUT(0)
2077#define DST_XTIME_AND__IN1          DISCRETE_INPUT(1)
2078#define DST_XTIME_AND_OUT_LOW       DISCRETE_INPUT(2)
2079#define DST_XTIME_AND_OUT_HIGH      DISCRETE_INPUT(3)
2080#define DST_XTIME_AND_INVERT        DISCRETE_INPUT(4)
2081
2082DISCRETE_STEP(dst_xtime_and)
2083{
2084   int in0 = (int)DST_XTIME_AND__IN0;
2085   int in1 = (int)DST_XTIME_AND__IN1;
2086   int out = 0;
2087   int out_is_energy = 1;
2088
2089   double x_time = 0;
2090   double x_time0 = DST_XTIME_AND__IN0 - in0;
2091   double x_time1 = DST_XTIME_AND__IN1 - in1;
2092
2093   int in0_has_xtime = x_time0 > 0 ? 1 : 0;
2094   int in1_has_xtime = x_time1 > 0 ? 1 : 0;
2095
2096   double out_low = DST_XTIME_AND_OUT_LOW;
2097   double out_high = DST_XTIME_AND_OUT_HIGH;
2098
2099   if (out_low ==0 && out_high == 0)
2100      out_is_energy = 0;
2101
2102   switch ((in0 << 3) | (in1 << 2) | (in0_has_xtime < 1) | in1_has_xtime)
2103   {
2104      // these are all 0
2105      //case XTIME__IN0_0__IN1_0__IN0_NOX__IN1_NOX:
2106      //case XTIME__IN0_0__IN1_1__IN0_NOX__IN1_NOX:
2107      //case XTIME__IN0_1__IN1_0__IN0_NOX__IN1_NOX:
2108      //case XTIME__IN0_0__IN1_0__IN0_NOX__IN1_X:
2109      //case XTIME__IN0_0__IN1_0__IN0_X__IN1_NOX:
2110      //case XTIME__IN0_0__IN1_1__IN0_NOX__IN1_X:
2111      //case XTIME__IN0_1__IN1_0__IN0_X__IN1_NOX:
2112      //  break;
2113
2114      case XTIME__IN0_1__IN1_1__IN0_NOX__IN1_NOX:
2115         out = 1;
2116         break;
2117
2118      case XTIME__IN0_0__IN1_1__IN0_X__IN1_NOX:
2119         /*
2120          * in0  1   ------
2121          *      0         -------
2122          *          ...^....^...
2123          *
2124          * in1  1   -------------
2125          *      0
2126          *          ...^....^...
2127          *
2128          * out  1   ------
2129          *      0         ------
2130          *          ...^....^...
2131          */
2132         x_time = x_time0;
2133         break;
2134
2135      case XTIME__IN0_1__IN1_0__IN0_NOX__IN1_X:
2136         /*
2137          * in0  1   -------------
2138          *      0
2139          *          ...^....^...
2140          *
2141          * in1  1   ------
2142          *      0         -------
2143          *          ...^....^...
2144          *
2145          * out  1   ------
2146          *      0         ------
2147          *          ...^....^...
2148          */
2149         x_time = x_time1;
2150         break;
2151
2152      case XTIME__IN0_0__IN1_0__IN0_X__IN1_X:
2153         /*
2154          * in0  1   -----              -------
2155          *      0        --------             ------
2156          *          ...^....^...       ...^....^...
2157          *
2158          * in1  1   -------            -----
2159          *      0          ------           --------
2160          *          ...^....^...       ...^....^...
2161          *
2162          * out  1   -----              -----
2163          *      0        -------            -------
2164          *          ...^....^...       ...^....^...
2165          */
2166         // use x_time of input that went to 0 first/longer
2167         if (x_time0 >= x_time1)
2168            x_time = x_time0;
2169         else
2170            x_time = x_time1;
2171         break;
2172
2173      case XTIME__IN0_0__IN1_1__IN0_X__IN1_X:
2174         /*
2175          * in0  1   -------           -----
2176          *      0          -----           -------
2177          *          ...^....^...      ...^....^...
2178          *
2179          * in1  1        -------             -----
2180          *      0   -----             -------
2181          *          ...^....^...      ...^....^...
2182          *
2183          * out  1        --
2184          *      0   -----  -----      ------------
2185          *          ...^....^...      ...^....^...
2186          */
2187         // may have went high for a bit in this cycle
2188         //if (x_time0 < x_time1)
2189         //  x_time = time1 - x_time0;
2190         break;
2191
2192      case XTIME__IN0_1__IN1_0__IN0_X__IN1_X:
2193         /*
2194          * in0  1        -------             -----
2195          *      0   -----             -------
2196          *          ...^....^...      ...^....^...
2197          *
2198          * in1  1   -------           -----
2199          *      0          -----           -------
2200          *          ...^....^...      ...^....^...
2201          *
2202          * out  1        --
2203          *      0   -----  -----      ------------
2204          *          ...^....^...      ...^....^...
2205          */
2206         // may have went high for a bit in this cycle
2207         //if (x_time0 > x_time1)
2208         //  x_time = x_time0 - x_time1;
2209         break;
2210
2211      case XTIME__IN0_1__IN1_1__IN0_NOX__IN1_X:
2212         /*
2213          * in0  1   ------------
2214          *      0
2215          *          ...^....^...
2216          *
2217          * in1  1         ------
2218          *      0   ------
2219          *          ...^....^...
2220          *
2221          * out  1         ------
2222          *      0   ------
2223          *          ...^....^...
2224          */
2225         out = 1;
2226         x_time = x_time1;
2227         break;
2228
2229      case XTIME__IN0_1__IN1_1__IN0_X__IN1_NOX:
2230         /*
2231          * in1  0         ------
2232          *      0   ------
2233          *          ...^....^...
2234          *
2235          * in1  1   ------------
2236          *      0
2237          *          ...^....^...
2238          *
2239          * out  1         ------
2240          *      0   ------
2241          *          ...^....^...
2242          */
2243         out = 1;
2244         x_time = x_time0;
2245         break;
2246
2247      case XTIME__IN0_1__IN1_1__IN0_X__IN1_X:
2248         /*
2249          * in0  1         ------          --------
2250          *      0   ------            ----
2251          *          ...^....^...      ...^....^...
2252          *
2253          * in1  1       --------            ------
2254          *      0   ----              ------
2255          *          ...^....^...      ...^....^...
2256          *
2257          * out  1         ------            ------
2258          *      0   ------            ------
2259          *          ...^....^...      ...^....^...
2260          */
2261         out = 1;
2262         if (x_time0 < x_time1)
2263            x_time = x_time0;
2264         else
2265            x_time = x_time1;
2266         break;
2267   }
2268
2269   if (DST_XTIME_AND_INVERT != 0)
2270      out ^= 1;
2271
2272   if (out_is_energy)
2273   {
2274      if (x_time > 0)
2275      {
2276         double diff = out_high - out_low;
2277         diff = out ? diff * x_time : diff * (1.0 - x_time);
2278         set_output(0,  out_low + diff);
2279      }
2280      else
2281         set_output(0,  out ? out_high : out_low);
2282   }
2283   else
2284      set_output(0,  out + x_time);
2285}
2286
2287
2288/************************************************************************
2289 *
2290 * DST_XTIME_OR - OR/NOR gate implementation using X_TIME
2291 *
2292 * If OUT_LOW and OUT_HIGH are defined then the output will be energy.
2293 * If they are both 0, then the output will be X_TIME logic.
2294 *
2295 ************************************************************************/
2296#define DST_XTIME_OR__IN0           DISCRETE_INPUT(0)
2297#define DST_XTIME_OR__IN1           DISCRETE_INPUT(1)
2298#define DST_XTIME_OR_OUT_LOW        DISCRETE_INPUT(2)
2299#define DST_XTIME_OR_OUT_HIGH       DISCRETE_INPUT(3)
2300#define DST_XTIME_OR_INVERT         DISCRETE_INPUT(4)
2301
2302DISCRETE_STEP(dst_xtime_or)
2303{
2304   int in0 = (int)DST_XTIME_OR__IN0;
2305   int in1 = (int)DST_XTIME_OR__IN1;
2306   int out = 1;
2307   int out_is_energy = 1;
2308
2309   double x_time = 0;
2310   double x_time0 = DST_XTIME_OR__IN0 - in0;
2311   double x_time1 = DST_XTIME_OR__IN1 - in1;
2312
2313   int in0_has_xtime = x_time0 > 0 ? 1 : 0;
2314   int in1_has_xtime = x_time1 > 0 ? 1 : 0;
2315
2316   double out_low = DST_XTIME_OR_OUT_LOW;
2317   double out_high = DST_XTIME_OR_OUT_HIGH;
2318
2319   if (out_low ==0 && out_high == 0)
2320      out_is_energy = 0;
2321
2322   switch ((in0 << 3) | (in1 << 2) | (in0_has_xtime < 1) | in1_has_xtime)
2323   {
2324      // these are all 1
2325      //case XTIME__IN0_1__IN1_1__IN0_NOX__IN1_NOX:
2326      //case XTIME__IN0_0__IN1_1__IN0_NOX__IN1_NOX:
2327      //case XTIME__IN0_1__IN1_0__IN0_NOX__IN1_NOX:
2328      //case XTIME__IN0_1__IN1_0__IN0_NOX__IN1_X:
2329      //case XTIME__IN0_0__IN1_1__IN0_X__IN1_NOX:
2330      //case XTIME__IN0_1__IN1_1__IN0_NOX__IN1_X:
2331      //case XTIME__IN0_1__IN1_1__IN0_X__IN1_NOX:
2332      //  break;
2333
2334      case XTIME__IN0_0__IN1_0__IN0_NOX__IN1_NOX:
2335         out = 0;
2336         break;
2337
2338      case XTIME__IN0_0__IN1_0__IN0_NOX__IN1_X:
2339         /*
2340          * in0  1
2341          *      0   -------------
2342          *          ...^....^...
2343          *
2344          * in1  1   ------
2345          *      0         -------
2346          *          ...^....^...
2347          *
2348          * out  1   ------
2349          *      0         ------
2350          *          ...^....^...
2351          */
2352         out = 0;
2353         x_time = x_time1;
2354         break;
2355
2356      case XTIME__IN0_0__IN1_0__IN0_X__IN1_NOX:
2357         /*
2358          * in0  1   ------
2359          *      0         -------
2360          *          ...^....^...
2361          *
2362          * in1  1
2363          *      0   -------------
2364          *          ...^....^...
2365          *
2366          * out  1   ------
2367          *      0         ------
2368          *          ...^....^...
2369          */
2370         out = 0;
2371         x_time = x_time0;
2372         break;
2373
2374      case XTIME__IN0_0__IN1_0__IN0_X__IN1_X:
2375         /*
2376          * in0  1   -----              -------
2377          *      0        --------             ------
2378          *          ...^....^...       ...^....^...
2379          *
2380          * in1  1   -------            -----
2381          *      0          ------           --------
2382          *          ...^....^...       ...^....^...
2383          *
2384          * out  1   -------            -------
2385          *      0          -----              -----
2386          *          ...^....^...       ...^....^...
2387          */
2388         out = 0;
2389         // use x_time of input that was 1 last/longer
2390         // this means at 0 for less x_time
2391         if (x_time0 > x_time1)
2392            x_time = x_time1;
2393         else
2394            x_time = x_time0;
2395         break;
2396
2397      case XTIME__IN0_0__IN1_1__IN0_NOX__IN1_X:
2398         /*
2399          * in0  1
2400          *      0   ------------
2401          *          ...^....^...
2402          *
2403          * in1  1         ------
2404          *      0   ------
2405          *          ...^....^...
2406          *
2407          * out  1         ------
2408          *      0   ------
2409          *          ...^....^...
2410          */
2411         x_time = x_time1;
2412         break;
2413
2414      case XTIME__IN0_1__IN1_0__IN0_X__IN1_NOX:
2415         /*
2416          * in0  1         ------
2417          *      0   ------
2418          *          ...^....^...
2419          *
2420          * in1  1
2421          *      0   ------------
2422          *          ...^....^...
2423          *
2424          * out  1         ------
2425          *      0   ------
2426          *          ...^....^...
2427          */
2428         x_time = x_time0;
2429         break;
2430
2431      case XTIME__IN0_0__IN1_1__IN0_X__IN1_X:
2432         /*
2433          * in0  1   -------           -----
2434          *      0          -----           -------
2435          *          ...^....^...      ...^....^...
2436          *
2437          * in1  1        -------             -----
2438          *      0   -----             -------
2439          *          ...^....^...      ...^....^...
2440          *
2441          * out  1   ------------      -----  -----
2442          *      0                          --
2443          *          ...^....^...      ...^....^...
2444          */
2445         // if (x_time0 > x_time1)
2446            /* Not sure if it is better to use 1
2447             * or the total energy which would smear the switch points together.
2448             * Let's try just using 1 */
2449            //x_time = xtime_0 - xtime_1;
2450         break;
2451
2452      case XTIME__IN0_1__IN1_0__IN0_X__IN1_X:
2453         /*
2454          * in0  1        -------             -----
2455          *      0   -----             -------
2456          *          ...^....^...      ...^....^...
2457          *
2458          * in1  1   -------           -----
2459          *      0          -----           -------
2460          *          ...^....^...      ...^....^...
2461          *
2462          * out  1   ------------      -----  -----
2463          *      0                          --
2464          *          ...^....^...      ...^....^...
2465          */
2466         //if (x_time0 < x_time1)
2467            /* Not sure if it is better to use 1
2468             * or the total energy which would smear the switch points together.
2469             * Let's try just using 1 */
2470            //x_time = xtime_1 - xtime_0;
2471         break;
2472
2473      case XTIME__IN0_1__IN1_1__IN0_X__IN1_X:
2474         /*
2475          * in0  1         ------          --------
2476          *      0   ------            ----
2477          *          ...^....^...      ...^....^...
2478          *
2479          * in1  1       --------            ------
2480          *      0   ----              ------
2481          *          ...^....^...      ...^....^...
2482          *
2483          * out  1       --------          --------
2484          *      0   ----              ----
2485          *          ...^....^...      ...^....^...
2486          */
2487         if (x_time0 > x_time1)
2488            x_time = x_time0;
2489         else
2490            x_time = x_time1;
2491         break;
2492   }
2493
2494   if (DST_XTIME_OR_INVERT != 0)
2495      out ^= 1;
2496
2497   if (out_is_energy)
2498   {
2499      if (x_time > 0)
2500      {
2501         double diff = out_high - out_low;
2502         diff = out ? diff * x_time : diff * (1.0 - x_time);
2503         set_output(0,  out_low + diff);
2504      }
2505      else
2506         set_output(0,  out ? out_high : out_low);
2507   }
2508   else
2509      set_output(0,  out + x_time);
2510}
2511
2512
2513/************************************************************************
2514 *
2515 * DST_XTIME_XOR - XOR/XNOR gate implementation using X_TIME
2516 *
2517 * If OUT_LOW and OUT_HIGH are defined then the output will be energy.
2518 * If they are both 0, then the output will be X_TIME logic.
2519 *
2520 ************************************************************************/
2521#define DST_XTIME_XOR__IN0          DISCRETE_INPUT(0)
2522#define DST_XTIME_XOR__IN1          DISCRETE_INPUT(1)
2523#define DST_XTIME_XOR_OUT_LOW       DISCRETE_INPUT(2)
2524#define DST_XTIME_XOR_OUT_HIGH      DISCRETE_INPUT(3)
2525#define DST_XTIME_XOR_INVERT        DISCRETE_INPUT(4)
2526
2527DISCRETE_STEP(dst_xtime_xor)
2528{
2529   int in0 = (int)DST_XTIME_XOR__IN0;
2530   int in1 = (int)DST_XTIME_XOR__IN1;
2531   int out = 1;
2532   int out_is_energy = 1;
2533
2534   double x_time = 0;
2535   double x_time0 = DST_XTIME_XOR__IN0 - in0;
2536   double x_time1 = DST_XTIME_XOR__IN1 - in1;
2537
2538   int in0_has_xtime = x_time0 > 0 ? 1 : 0;
2539   int in1_has_xtime = x_time1 > 0 ? 1 : 0;
2540
2541   double out_low = DST_XTIME_XOR_OUT_LOW;
2542   double out_high = DST_XTIME_XOR_OUT_HIGH;
2543
2544   if (out_low ==0 && out_high == 0)
2545      out_is_energy = 0;
2546
2547   switch ((in0 << 3) | (in1 << 2) | (in0_has_xtime < 1) | in1_has_xtime)
2548   {
2549      // these are all 1
2550      //case XTIME__IN0_0__IN1_1__IN0_NOX__IN1_NOX:
2551      //case XTIME__IN0_1__IN1_0__IN0_NOX__IN1_NOX:
2552      //  break;
2553
2554      case XTIME__IN0_1__IN1_1__IN0_NOX__IN1_NOX:
2555      case XTIME__IN0_0__IN1_0__IN0_NOX__IN1_NOX:
2556         out = 0;
2557         break;
2558
2559      case XTIME__IN0_1__IN1_0__IN0_X__IN1_NOX:
2560         /*
2561          * in0  1         ------
2562          *      0   ------
2563          *          ...^....^...
2564          *
2565          * in1  1
2566          *      0   ------------
2567          *          ...^....^...
2568          *
2569          * out  1         ------
2570          *      0   ------
2571          *          ...^....^...
2572          */
2573      case XTIME__IN0_0__IN1_1__IN0_X__IN1_NOX:
2574         /*
2575          * in0  1   ------
2576          *      0         -------
2577          *          ...^....^...
2578          *
2579          * in1  1   -------------
2580          *      0
2581          *          ...^....^...
2582          *
2583          * out  1         ------
2584          *      0   ------
2585          *          ...^....^...
2586          */
2587         x_time = x_time0;
2588         break;
2589
2590      case XTIME__IN0_0__IN1_1__IN0_NOX__IN1_X:
2591         /*
2592          * in0  1
2593          *      0   ------------
2594          *          ...^....^...
2595          *
2596          * in1  1         ------
2597          *      0   ------
2598          *          ...^....^...
2599          *
2600          * out  1         ------
2601          *      0   ------
2602          *          ...^....^...
2603          */
2604      case XTIME__IN0_1__IN1_0__IN0_NOX__IN1_X:
2605         /*
2606          * in0  1   -------------
2607          *      0
2608          *          ...^....^...
2609          *
2610          * in1  1   ------
2611          *      0         -------
2612          *          ...^....^...
2613          *
2614          * out  1         ------
2615          *      0   ------
2616          *          ...^....^...
2617          */
2618         x_time = x_time1;
2619         break;
2620
2621      case XTIME__IN0_0__IN1_0__IN0_X__IN1_NOX:
2622         /*
2623          * in0  1   ------
2624          *      0         ------
2625          *          ...^....^...
2626          *
2627          * in1  1
2628          *      0   ------------
2629          *          ...^....^...
2630          *
2631          * out  1   ------
2632          *      0         ------
2633          *          ...^....^...
2634          */
2635      case XTIME__IN0_1__IN1_1__IN0_X__IN1_NOX:
2636         /*
2637          * in1  0         ------
2638          *      0   ------
2639          *          ...^....^...
2640          *
2641          * in1  1   ------------
2642          *      0
2643          *          ...^....^...
2644          *
2645          * out  1   ------
2646          *      0         ------
2647          *          ...^....^...
2648          */
2649         out = 0;
2650         x_time = x_time0;
2651         break;
2652
2653      case XTIME__IN0_0__IN1_0__IN0_NOX__IN1_X:
2654         /*
2655          * in0  1
2656          *      0   ------------
2657          *          ...^....^...
2658          *
2659          * in1  1   ------
2660          *      0         ------
2661          *          ...^....^...
2662          *
2663          * out  1   ------
2664          *      0         ------
2665          *          ...^....^...
2666          */
2667      case XTIME__IN0_1__IN1_1__IN0_NOX__IN1_X:
2668         /*
2669          * in0  1   ------------
2670          *      0
2671          *          ...^....^...
2672          *
2673          * in1  1         ------
2674          *      0   ------
2675          *          ...^....^...
2676          *
2677          * out  1   ------
2678          *      0         ------
2679          *          ...^....^...
2680          */
2681         out = 0;
2682         x_time = x_time1;
2683         break;
2684
2685      case XTIME__IN0_0__IN1_0__IN0_X__IN1_X:
2686         /*
2687          * in0  1   -----              -------
2688          *      0        -------              -----
2689          *          ...^....^...       ...^....^...
2690          *
2691          * in1  1   -------            -----
2692          *      0          -----            -------
2693          *          ...^....^...       ...^....^...
2694          *
2695          * out  1        --                 --
2696          *      0   -----  -----       -----  -----
2697          *          ...^....^...       ...^....^...
2698          */
2699      case XTIME__IN0_1__IN1_1__IN0_X__IN1_X:
2700         /*
2701          * in0  1         ------          --------
2702          *      0   ------            ----
2703          *          ...^....^...      ...^....^...
2704          *
2705          * in1  1       --------            ------
2706          *      0   ----              ------
2707          *          ...^....^...      ...^....^...
2708          *
2709          * out  1       --                --
2710          *      0   ----  ------      ----  ------
2711          *          ...^....^...      ...^....^...
2712          */
2713         out = 0;
2714         /* Not sure if it is better to use 0
2715          * or the total energy which would smear the switch points together.
2716          * Let's try just using 0 */
2717         // x_time = abs(x_time0 - x_time1);
2718         break;
2719
2720      case XTIME__IN0_0__IN1_1__IN0_X__IN1_X:
2721         /*
2722          * in0  1   -------           -----
2723          *      0          -----           -------
2724          *          ...^....^...      ...^....^...
2725          *
2726          * in1  1        -------             -----
2727          *      0   -----             -------
2728          *          ...^....^...      ...^....^...
2729          *
2730          * out  1   -----  -----      -----  -----
2731          *      0        --                --
2732          *          ...^....^...      ...^....^...
2733          */
2734      case XTIME__IN0_1__IN1_0__IN0_X__IN1_X:
2735         /*
2736          * in0  1        -------             -----
2737          *      0   -----             -------
2738          *          ...^....^...      ...^....^...
2739          *
2740          * in1  1   -------           -----
2741          *      0          -----           -------
2742          *          ...^....^...      ...^....^...
2743          *
2744          * out  1   -----  -----      -----  -----
2745          *      0        --                --
2746          *          ...^....^...      ...^....^...
2747          */
2748         /* Not sure if it is better to use 1
2749          * or the total energy which would smear the switch points together.
2750          * Let's try just using 1 */
2751         // x_time = 1.0 - abs(x_time0 - x_time1);
2752         break;
2753}
2754
2755   if (DST_XTIME_XOR_INVERT != 0)
2756      out ^= 1;
2757
2758   if (out_is_energy)
2759   {
2760      if (x_time > 0)
2761      {
2762         double diff = out_high - out_low;
2763         diff = out ? diff * x_time : diff * (1.0 - x_time);
2764         set_output(0,  out_low + diff);
2765      }
2766      else
2767         set_output(0,  out ? out_high : out_low);
2768   }
2769   else
2770      set_output(0,  out + x_time);
2771}
trunk/src/emu/sound/disc_flt.c
r28731r28732
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_CRFILTER          - Simple CR filter & also highpass filter
12 * DST_FILTER1           - Generic 1st order filter
13 * DST_FILTER2           - Generic 2nd order filter
14 * DST_OP_AMP_FILT       - Op Amp filter circuits
15 * DST_RC_CIRCUIT_1      - RC charge/discharge circuit
16 * DST_RCDISC            - Simple discharging RC
17 * DST_RCDISC2           - Simple charge R1/C, discharge R0/C
18 * DST_RCDISC3           - Simple charge R1/c, discharge R0*R1/(R0+R1)/C
19 * DST_RCDISC4           - Various charge/discharge circuits
20 * DST_RCDISC5           - Diode in series with R//C
21 * DST_RCDISC_MOD        - RC triggered by logic and modulated
22 * DST_RCFILTER          - Simple RC filter & also lowpass filter
23 * DST_RCFILTER_SW       - Usage of node_description values for switchable RC filter
24 * DST_RCINTEGRATE       - Two diode inputs, transistor and a R/C charge
25 *                         discharge network
26 * DST_SALLEN_KEY        - Sallen-Key filter circuit
27 *
28 ************************************************************************/
29
30
31/************************************************************************
32 *
33 * DST_CRFILTER - Usage of node_description values for CR filter
34 *
35 * input[0]    - Enable input value
36 * input[1]    - input value
37 * input[2]    - Resistor value (initialization only)
38 * input[3]    - Capacitor Value (initialization only)
39 * input[4]    - Voltage reference. Usually 0V.
40 *
41 ************************************************************************/
42#define DST_CRFILTER__IN        DISCRETE_INPUT(0)
43#define DST_CRFILTER__R         DISCRETE_INPUT(1)
44#define DST_CRFILTER__C         DISCRETE_INPUT(2)
45#define DST_CRFILTER__VREF      DISCRETE_INPUT(3)
46
47DISCRETE_STEP(dst_crfilter)
48{
49   if (UNEXPECTED(m_has_rc_nodes))
50   {
51      double rc = DST_CRFILTER__R * DST_CRFILTER__C;
52      if (rc != m_rc)
53      {
54         m_rc = rc;
55         m_exponent = RC_CHARGE_EXP(rc);
56      }
57   }
58
59   double v_out = DST_CRFILTER__IN - m_vCap;
60   double v_diff = v_out - DST_CRFILTER__VREF;
61   set_output(0,  v_out);
62   m_vCap += v_diff * m_exponent;
63}
64
65DISCRETE_RESET(dst_crfilter)
66{
67   m_has_rc_nodes = this->input_is_node() & 0x6;
68   m_rc = DST_CRFILTER__R * DST_CRFILTER__C;
69   m_exponent = RC_CHARGE_EXP(m_rc);
70   m_vCap = 0;
71   set_output(0,  DST_CRFILTER__IN);
72}
73
74
75/************************************************************************
76 *
77 * DST_FILTER1 - Generic 1st order filter
78 *
79 * input[0]    - Enable input value
80 * input[1]    - input value
81 * input[2]    - Frequency value (initialization only)
82 * input[3]    - Filter type (initialization only)
83 *
84 ************************************************************************/
85#define DST_FILTER1__ENABLE DISCRETE_INPUT(0)
86#define DST_FILTER1__IN     DISCRETE_INPUT(1)
87#define DST_FILTER1__FREQ   DISCRETE_INPUT(2)
88#define DST_FILTER1__TYPE   DISCRETE_INPUT(3)
89
90static void calculate_filter1_coefficients(discrete_base_node *node, double fc, double type,
91                                 struct discrete_filter_coeff &coeff)
92{
93   double den, w, two_over_T;
94
95   /* calculate digital filter coefficents */
96   /*w = 2.0*M_PI*fc; no pre-warping */
97   w = node->sample_rate()*2.0*tan(M_PI*fc/node->sample_rate()); /* pre-warping */
98   two_over_T = 2.0*node->sample_rate();
99
100   den = w + two_over_T;
101   coeff.a1 = (w - two_over_T)/den;
102   if (type == DISC_FILTER_LOWPASS)
103   {
104      coeff.b0 = coeff.b1 = w/den;
105   }
106   else if (type == DISC_FILTER_HIGHPASS)
107   {
108      coeff.b0 = two_over_T/den;
109      coeff.b1 = -(coeff.b0);
110   }
111   else
112   {
113      /* FIXME: reenable */
114      //node->m_device->discrete_log("calculate_filter1_coefficients() - Invalid filter type for 1st order filter.");
115   }
116}
117
118DISCRETE_STEP(dst_filter1)
119{
120   double gain = 1.0;
121   double v_out;
122
123   if (DST_FILTER1__ENABLE == 0.0)
124   {
125      gain = 0.0;
126   }
127
128   v_out = -m_fc.a1*m_fc.y1 + m_fc.b0*gain*DST_FILTER1__IN + m_fc.b1*m_fc.x1;
129
130   m_fc.x1 = gain*DST_FILTER1__IN;
131   m_fc.y1 = v_out;
132   set_output(0, v_out);
133}
134
135DISCRETE_RESET(dst_filter1)
136{
137   calculate_filter1_coefficients(this, DST_FILTER1__FREQ, DST_FILTER1__TYPE, m_fc);
138   set_output(0,  0);
139}
140
141
142/************************************************************************
143 *
144 * DST_FILTER2 - Generic 2nd order filter
145 *
146 * input[0]    - Enable input value
147 * input[1]    - input value
148 * input[2]    - Frequency value (initialization only)
149 * input[3]    - Damping value (initialization only)
150 * input[4]    - Filter type (initialization only)
151 *
152 ************************************************************************/
153#define DST_FILTER2__ENABLE DISCRETE_INPUT(0)
154#define DST_FILTER2__IN     DISCRETE_INPUT(1)
155#define DST_FILTER2__FREQ   DISCRETE_INPUT(2)
156#define DST_FILTER2__DAMP   DISCRETE_INPUT(3)
157#define DST_FILTER2__TYPE   DISCRETE_INPUT(4)
158
159static void calculate_filter2_coefficients(discrete_base_node *node,
160                                 double fc, double d, double type,
161                                 struct discrete_filter_coeff &coeff)
162{
163   double w;   /* cutoff freq, in radians/sec */
164   double w_squared;
165   double den; /* temp variable */
166   double two_over_T = 2 * node->sample_rate();
167   double two_over_T_squared = two_over_T * two_over_T;
168
169   /* calculate digital filter coefficents */
170   /*w = 2.0*M_PI*fc; no pre-warping */
171   w = node->sample_rate() * 2.0 * tan(M_PI * fc / node->sample_rate()); /* pre-warping */
172   w_squared = w * w;
173
174   den = two_over_T_squared + d*w*two_over_T + w_squared;
175
176   coeff.a1 = 2.0 * (-two_over_T_squared + w_squared) / den;
177   coeff.a2 = (two_over_T_squared - d * w * two_over_T + w_squared) / den;
178
179   if (type == DISC_FILTER_LOWPASS)
180   {
181      coeff.b0 = coeff.b2 = w_squared/den;
182      coeff.b1 = 2.0 * (coeff.b0);
183   }
184   else if (type == DISC_FILTER_BANDPASS)
185   {
186      coeff.b0 = d * w * two_over_T / den;
187      coeff.b1 = 0.0;
188      coeff.b2 = -(coeff.b0);
189   }
190   else if (type == DISC_FILTER_HIGHPASS)
191   {
192      coeff.b0 = coeff.b2 = two_over_T_squared / den;
193      coeff.b1 = -2.0 * (coeff.b0);
194   }
195   else
196   {
197      /* FIXME: reenable */
198      //node->device->discrete_log("calculate_filter2_coefficients() - Invalid filter type for 2nd order filter.");
199   }
200}
201
202DISCRETE_STEP(dst_filter2)
203{
204   double gain = 1.0;
205   double v_out;
206
207   if (DST_FILTER2__ENABLE == 0.0)
208   {
209      gain = 0.0;
210   }
211
212   v_out = -m_fc.a1 * m_fc.y1 - m_fc.a2 * m_fc.y2 +
213               m_fc.b0 * gain * DST_FILTER2__IN + m_fc.b1 * m_fc.x1 + m_fc.b2 * m_fc.x2;
214
215   m_fc.x2 = m_fc.x1;
216   m_fc.x1 = gain * DST_FILTER2__IN;
217   m_fc.y2 = m_fc.y1;
218   m_fc.y1 = v_out;
219   set_output(0, v_out);
220}
221
222DISCRETE_RESET(dst_filter2)
223{
224   calculate_filter2_coefficients(this, DST_FILTER2__FREQ, DST_FILTER2__DAMP, DST_FILTER2__TYPE,
225                           m_fc);
226   set_output(0,  0);
227}
228
229
230/************************************************************************
231 *
232 * DST_OP_AMP_FILT - Op Amp filter circuit RC filter
233 *
234 * input[0]    - Enable input value
235 * input[1]    - IN0 node
236 * input[2]    - IN1 node
237 * input[3]    - Filter Type
238 *
239 * also passed discrete_op_amp_filt_info structure
240 *
241 * Mar 2004, D Renaud.
242 ************************************************************************/
243#define DST_OP_AMP_FILT__ENABLE DISCRETE_INPUT(0)
244#define DST_OP_AMP_FILT__INP1   DISCRETE_INPUT(1)
245#define DST_OP_AMP_FILT__INP2   DISCRETE_INPUT(2)
246#define DST_OP_AMP_FILT__TYPE   DISCRETE_INPUT(3)
247
248DISCRETE_STEP(dst_op_amp_filt)
249{
250   DISCRETE_DECLARE_INFO(discrete_op_amp_filt_info)
251   double v_out = 0;
252
253   double i, v = 0;
254
255   if (DST_OP_AMP_FILT__ENABLE)
256   {
257      if (m_is_norton)
258      {
259         v = DST_OP_AMP_FILT__INP1 - OP_AMP_NORTON_VBE;
260         if (v < 0) v = 0;
261      }
262      else
263      {
264         /* Millman the input voltages. */
265         i  = m_iFixed;
266         switch (m_type)
267         {
268            case DISC_OP_AMP_FILTER_IS_LOW_PASS_1_A:
269               i += (DST_OP_AMP_FILT__INP1 - DST_OP_AMP_FILT__INP2) / info->r1;
270               if (info->r2 != 0)
271                  i += (m_vP - DST_OP_AMP_FILT__INP2) / info->r2;
272               if (info->r3 != 0)
273                  i += (m_vN - DST_OP_AMP_FILT__INP2) / info->r3;
274               break;
275            default:
276               i += (DST_OP_AMP_FILT__INP1 - m_vRef) / info->r1;
277               if (info->r2 != 0)
278                  i += (DST_OP_AMP_FILT__INP2 - m_vRef) / info->r2;
279               break;
280         }
281         v = i * m_rTotal;
282      }
283
284      switch (m_type)
285      {
286         case DISC_OP_AMP_FILTER_IS_LOW_PASS_1:
287            m_vC1 += (v - m_vC1) * m_exponentC1;
288            v_out = m_vC1 * m_gain + info->vRef;
289            break;
290
291         case DISC_OP_AMP_FILTER_IS_LOW_PASS_1_A:
292            m_vC1 += (v - m_vC1) * m_exponentC1;
293            v_out = m_vC1 * m_gain + DST_OP_AMP_FILT__INP2;
294            break;
295
296         case DISC_OP_AMP_FILTER_IS_HIGH_PASS_1:
297            v_out = (v - m_vC1) * m_gain + info->vRef;
298            m_vC1 += (v - m_vC1) * m_exponentC1;
299            break;
300
301         case DISC_OP_AMP_FILTER_IS_BAND_PASS_1:
302            v_out = (v - m_vC2);
303            m_vC2 += (v - m_vC2) * m_exponentC2;
304            m_vC1 += (v_out - m_vC1) * m_exponentC1;
305            v_out = m_vC1 * m_gain + info->vRef;
306            break;
307
308         case DISC_OP_AMP_FILTER_IS_BAND_PASS_0 | DISC_OP_AMP_IS_NORTON:
309            m_vC1 += (v - m_vC1) * m_exponentC1;
310            m_vC2 += (m_vC1 - m_vC2) * m_exponentC2;
311            v = m_vC2;
312            v_out = v - m_vC3;
313            m_vC3 += (v - m_vC3) * m_exponentC3;
314            i = v_out / m_rTotal;
315            v_out = (m_iFixed - i) * info->rF;
316            break;
317
318         case DISC_OP_AMP_FILTER_IS_HIGH_PASS_0 | DISC_OP_AMP_IS_NORTON:
319            v_out = v - m_vC1;
320            m_vC1 += (v - m_vC1) * m_exponentC1;
321            i = v_out / m_rTotal;
322            v_out = (m_iFixed - i) * info->rF;
323            break;
324
325         case DISC_OP_AMP_FILTER_IS_BAND_PASS_1M:
326         case DISC_OP_AMP_FILTER_IS_BAND_PASS_1M | DISC_OP_AMP_IS_NORTON:
327            v_out = -m_fc.a1 * m_fc.y1 - m_fc.a2 * m_fc.y2 +
328                        m_fc.b0 * v + m_fc.b1 * m_fc.x1 + m_fc.b2 * m_fc.x2 +
329                        m_vRef;
330            m_fc.x2 = m_fc.x1;
331            m_fc.x1 = v;
332            m_fc.y2 = m_fc.y1;
333            break;
334      }
335
336      /* Clip the output to the voltage rails.
337       * This way we get the original distortion in all it's glory.
338       */
339      if (v_out > m_vP) v_out = m_vP;
340      if (v_out < m_vN) v_out = m_vN;
341      m_fc.y1 = v_out - m_vRef;
342      set_output(0, v_out);
343   }
344   else
345      set_output(0, 0);
346
347}
348
349DISCRETE_RESET(dst_op_amp_filt)
350{
351   DISCRETE_DECLARE_INFO(discrete_op_amp_filt_info)
352
353   /* Convert the passed filter type into an int for easy use. */
354   m_type = (int)DST_OP_AMP_FILT__TYPE & DISC_OP_AMP_FILTER_TYPE_MASK;
355   m_is_norton = (int)DST_OP_AMP_FILT__TYPE & DISC_OP_AMP_IS_NORTON;
356
357   if (m_is_norton)
358   {
359      m_vRef = 0;
360      m_rTotal = info->r1;
361      if (m_type == (DISC_OP_AMP_FILTER_IS_BAND_PASS_0 | DISC_OP_AMP_IS_NORTON))
362         m_rTotal += info->r2 +  info->r3;
363
364      /* Setup the current to the + input. */
365      m_iFixed = (info->vP - OP_AMP_NORTON_VBE) / info->r4;
366
367      /* Set the output max. */
368      m_vP =  info->vP - OP_AMP_NORTON_VBE;
369      m_vN =  info->vN;
370   }
371   else
372   {
373      m_vRef = info->vRef;
374      /* Set the output max. */
375      m_vP =  info->vP - OP_AMP_VP_RAIL_OFFSET;
376      m_vN =  info->vN;
377
378      /* Work out the input resistance.  It is all input and bias resistors in parallel. */
379      m_rTotal  = 1.0 / info->r1;         /* There has to be an R1.  Otherwise the table is wrong. */
380      if (info->r2 != 0) m_rTotal += 1.0 / info->r2;
381      if (info->r3 != 0) m_rTotal += 1.0 / info->r3;
382      m_rTotal = 1.0 / m_rTotal;
383
384      m_iFixed = 0;
385
386      m_rRatio = info->rF / (m_rTotal + info->rF);
387      m_gain = -info->rF / m_rTotal;
388   }
389
390   switch (m_type)
391   {
392      case DISC_OP_AMP_FILTER_IS_LOW_PASS_1:
393      case DISC_OP_AMP_FILTER_IS_LOW_PASS_1_A:
394         m_exponentC1 = RC_CHARGE_EXP(info->rF * info->c1);
395         m_exponentC2 =  0;
396         break;
397      case DISC_OP_AMP_FILTER_IS_HIGH_PASS_1:
398         m_exponentC1 = RC_CHARGE_EXP(m_rTotal * info->c1);
399         m_exponentC2 =  0;
400         break;
401      case DISC_OP_AMP_FILTER_IS_BAND_PASS_1:
402         m_exponentC1 = RC_CHARGE_EXP(info->rF * info->c1);
403         m_exponentC2 = RC_CHARGE_EXP(m_rTotal * info->c2);
404         break;
405      case DISC_OP_AMP_FILTER_IS_BAND_PASS_1M | DISC_OP_AMP_IS_NORTON:
406         if (info->r2 == 0)
407            m_rTotal = info->r1;
408         else
409            m_rTotal = RES_2_PARALLEL(info->r1, info->r2);
410      case DISC_OP_AMP_FILTER_IS_BAND_PASS_1M:
411      {
412         double fc = 1.0 / (2 * M_PI * sqrt(m_rTotal * info->rF * info->c1 * info->c2));
413         double d  = (info->c1 + info->c2) / sqrt(info->rF / m_rTotal * info->c1 * info->c2);
414         double gain = -info->rF / m_rTotal * info->c2 / (info->c1 + info->c2);
415
416         calculate_filter2_coefficients(this, fc, d, DISC_FILTER_BANDPASS, m_fc);
417         m_fc.b0 *= gain;
418         m_fc.b1 *= gain;
419         m_fc.b2 *= gain;
420
421         if (m_is_norton)
422            m_vRef = (info->vP - OP_AMP_NORTON_VBE) / info->r3 * info->rF;
423         else
424            m_vRef = info->vRef;
425
426         break;
427      }
428      case DISC_OP_AMP_FILTER_IS_BAND_PASS_0 | DISC_OP_AMP_IS_NORTON:
429         m_exponentC1 = RC_CHARGE_EXP(RES_2_PARALLEL(info->r1, info->r2 + info->r3 + info->r4) * info->c1);
430         m_exponentC2 = RC_CHARGE_EXP(RES_2_PARALLEL(info->r1 + info->r2, info->r3 + info->r4) * info->c2);
431         m_exponentC3 = RC_CHARGE_EXP((info->r1 + info->r2 + info->r3 + info->r4) * info->c3);
432         break;
433      case DISC_OP_AMP_FILTER_IS_HIGH_PASS_0 | DISC_OP_AMP_IS_NORTON:
434         m_exponentC1 = RC_CHARGE_EXP(info->r1 * info->c1);
435         break;
436   }
437
438   /* At startup there is no charge on the caps and output is 0V in relation to vRef. */
439   m_vC1 = 0;
440   m_vC1b = 0;
441   m_vC2 = 0;
442   m_vC3 = 0;
443
444   set_output(0,  info->vRef);
445}
446
447
448/************************************************************************
449 *
450 * DST_RC_CIRCUIT_1 - RC charge/discharge circuit
451 *
452 ************************************************************************/
453#define DST_RC_CIRCUIT_1__IN0       DISCRETE_INPUT(0)
454#define DST_RC_CIRCUIT_1__IN1       DISCRETE_INPUT(1)
455#define DST_RC_CIRCUIT_1__R         DISCRETE_INPUT(2)
456#define DST_RC_CIRCUIT_1__C         DISCRETE_INPUT(3)
457
458#define CD4066_R_ON 270
459
460DISCRETE_STEP( dst_rc_circuit_1 )
461{
462   if (DST_RC_CIRCUIT_1__IN0 == 0)
463      if (DST_RC_CIRCUIT_1__IN1 == 0)
464         /* cap is floating and does not change charge */
465         /* output is pulled to ground */
466         set_output(0,  0);
467      else
468      {
469         /* cap is discharged */
470         m_v_cap -= m_v_cap * m_exp_2;
471         set_output(0,  m_v_cap * m_v_drop);
472      }
473   else
474      if (DST_RC_CIRCUIT_1__IN1 == 0)
475      {
476         /* cap is charged */
477         m_v_cap += (5.0 - m_v_cap) * m_exp_1;
478         /* output is pulled to ground */
479         set_output(0,  0);
480      }
481      else
482      {
483         /* cap is charged slightly less */
484         m_v_cap += (m_v_charge_1_2 - m_v_cap) * m_exp_1_2;
485         set_output(0,  m_v_cap * m_v_drop);
486      }
487}
488
489DISCRETE_RESET( dst_rc_circuit_1 )
490{
491   /* the charging voltage across the cap based on in2*/
492   m_v_drop =  RES_VOLTAGE_DIVIDER(CD4066_R_ON, CD4066_R_ON + DST_RC_CIRCUIT_1__R);
493   m_v_charge_1_2 = 5.0 * m_v_drop;
494   m_v_cap = 0;
495
496   /* precalculate charging exponents */
497   /* discharge cap - in1 = 0, in2 = 1*/
498   m_exp_2 = RC_CHARGE_EXP((CD4066_R_ON + DST_RC_CIRCUIT_1__R) * DST_RC_CIRCUIT_1__C);
499   /* charge cap - in1 = 1, in2 = 0 */
500   m_exp_1 = RC_CHARGE_EXP(CD4066_R_ON * DST_RC_CIRCUIT_1__C);
501   /* charge cap - in1 = 1, in2 = 1 */
502   m_exp_1_2 = RC_CHARGE_EXP(RES_2_PARALLEL(CD4066_R_ON, CD4066_R_ON + DST_RC_CIRCUIT_1__R) * DST_RC_CIRCUIT_1__C);
503
504   /* starts at 0 until cap starts charging */
505   set_output(0,  0);
506}
507
508/************************************************************************
509 *
510 * DST_RCDISC -   Usage of node_description values for RC discharge
511 *                (inverse slope of DST_RCFILTER)
512 *
513 * input[0]    - Enable input value
514 * input[1]    - input value
515 * input[2]    - Resistor value (initialization only)
516 * input[3]    - Capacitor Value (initialization only)
517 *
518 ************************************************************************/
519#define DST_RCDISC__ENABLE  DISCRETE_INPUT(0)
520#define DST_RCDISC__IN      DISCRETE_INPUT(1)
521#define DST_RCDISC__R       DISCRETE_INPUT(2)
522#define DST_RCDISC__C       DISCRETE_INPUT(3)
523
524DISCRETE_STEP(dst_rcdisc)
525{
526   switch (m_state)
527   {
528      case 0:     /* waiting for trigger  */
529         if(DST_RCDISC__ENABLE)
530         {
531            m_state = 1;
532            m_t = 0;
533         }
534         set_output(0,  0);
535         break;
536
537      case 1:
538         if (DST_RCDISC__ENABLE)
539         {
540            set_output(0,  DST_RCDISC__IN * exp(m_t / m_exponent0));
541            m_t += this->sample_time();
542         } else
543         {
544            m_state = 0;
545         }
546   }
547}
548
549DISCRETE_RESET(dst_rcdisc)
550{
551   set_output(0,  0);
552
553   m_state = 0;
554   m_t = 0;
555   m_exponent0=-1.0 * DST_RCDISC__R * DST_RCDISC__C;
556}
557
558
559/************************************************************************
560 *
561 * DST_RCDISC2 -  Usage of node_description values for RC discharge
562 *                Has switchable charge resistor/input
563 *
564 * input[0]    - Switch input value
565 * input[1]    - input[0] value
566 * input[2]    - Resistor0 value (initialization only)
567 * input[3]    - input[1] value
568 * input[4]    - Resistor1 value (initialization only)
569 * input[5]    - Capacitor Value (initialization only)
570 *
571 ************************************************************************/
572#define DST_RCDISC2__ENABLE DISCRETE_INPUT(0)
573#define DST_RCDISC2__IN0    DISCRETE_INPUT(1)
574#define DST_RCDISC2__R0     DISCRETE_INPUT(2)
575#define DST_RCDISC2__IN1    DISCRETE_INPUT(3)
576#define DST_RCDISC2__R1     DISCRETE_INPUT(4)
577#define DST_RCDISC2__C      DISCRETE_INPUT(5)
578
579DISCRETE_STEP(dst_rcdisc2)
580{
581   double diff;
582
583   /* Works differently to other as we are always on, no enable */
584   /* exponential based in difference between input/output   */
585
586   diff = ((DST_RCDISC2__ENABLE == 0) ? DST_RCDISC2__IN0 : DST_RCDISC2__IN1) - m_v_out;
587   diff = diff - (diff * ((DST_RCDISC2__ENABLE == 0) ? m_exponent0 : m_exponent1));
588   m_v_out += diff;
589   set_output(0, m_v_out);
590}
591
592DISCRETE_RESET(dst_rcdisc2)
593{
594   m_v_out = 0;
595
596   m_state = 0;
597   m_t = 0;
598   m_exponent0 = RC_DISCHARGE_EXP(DST_RCDISC2__R0 * DST_RCDISC2__C);
599   m_exponent1 = RC_DISCHARGE_EXP(DST_RCDISC2__R1 * DST_RCDISC2__C);
600}
601
602/************************************************************************
603 *
604 * DST_RCDISC3 -  Usage of node_description values for RC discharge
605 *
606 *
607 * input[0]    - Enable
608 * input[1]    - input  value
609 * input[2]    - Resistor0 value (initialization only)
610 * input[4]    - Resistor1 value (initialization only)
611 * input[5]    - Capacitor Value (initialization only)
612 * input[6]    - Diode Junction voltage (initialization only)
613 *
614 ************************************************************************/
615#define DST_RCDISC3__ENABLE DISCRETE_INPUT(0)
616#define DST_RCDISC3__IN     DISCRETE_INPUT(1)
617#define DST_RCDISC3__R1     DISCRETE_INPUT(2)
618#define DST_RCDISC3__R2     DISCRETE_INPUT(3)
619#define DST_RCDISC3__C      DISCRETE_INPUT(4)
620#define DST_RCDISC3__DJV    DISCRETE_INPUT(5)
621
622DISCRETE_STEP(dst_rcdisc3)
623{
624   double diff;
625
626   /* Exponential based in difference between input/output   */
627
628   if(DST_RCDISC3__ENABLE)
629   {
630      diff = DST_RCDISC3__IN - m_v_out;
631      if (m_v_diode > 0)
632      {
633         if (diff > 0)
634         {
635            diff = diff * m_exponent0;
636         }
637         else if (diff < -m_v_diode)
638         {
639            diff = diff * m_exponent1;
640         }
641         else
642         {
643            diff = diff * m_exponent0;
644         }
645      }
646      else
647      {
648         if (diff < 0)
649         {
650            diff = diff * m_exponent0;
651         }
652         else if (diff > -m_v_diode)
653         {
654            diff = diff * m_exponent1;
655         }
656         else
657         {
658            diff = diff * m_exponent0;
659         }
660      }
661      m_v_out += diff;
662      set_output(0, m_v_out);
663   }
664   else
665   {
666      set_output(0, 0);
667   }
668}
669
670DISCRETE_RESET(dst_rcdisc3)
671{
672   m_v_out = 0;
673
674   m_state = 0;
675   m_t = 0;
676   m_v_diode = DST_RCDISC3__DJV;
677   m_exponent0 = RC_CHARGE_EXP(DST_RCDISC3__R1 * DST_RCDISC3__C);
678   m_exponent1 = RC_CHARGE_EXP(RES_2_PARALLEL(DST_RCDISC3__R1, DST_RCDISC3__R2) * DST_RCDISC3__C);
679}
680
681
682/************************************************************************
683 *
684 * DST_RCDISC4 -  Various charge/discharge circuits
685 *
686 * input[0]    - Enable input value
687 * input[1]    - input value
688 * input[2]    - R1 Resistor value (initialization only)
689 * input[2]    - R2 Resistor value (initialization only)
690 * input[4]    - C1 Capacitor Value (initialization only)
691 * input[4]    - vP power source (initialization only)
692 * input[4]    - circuit type (initialization only)
693 *
694 ************************************************************************/
695#define DST_RCDISC4__ENABLE DISCRETE_INPUT(0)
696#define DST_RCDISC4__IN     DISCRETE_INPUT(1)
697#define DST_RCDISC4__R1     DISCRETE_INPUT(2)
698#define DST_RCDISC4__R2     DISCRETE_INPUT(3)
699#define DST_RCDISC4__R3     DISCRETE_INPUT(4)
700#define DST_RCDISC4__C1     DISCRETE_INPUT(5)
701#define DST_RCDISC4__VP     DISCRETE_INPUT(6)
702#define DST_RCDISC4__TYPE   DISCRETE_INPUT(7)
703
704DISCRETE_STEP(dst_rcdisc4)
705{
706   int inp1 = (DST_RCDISC4__IN == 0) ? 0 : 1;
707   double v_out = 0;
708
709   if (DST_RCDISC4__ENABLE == 0)
710   {
711      set_output(0, 0);
712      return;
713   }
714
715   switch (m_type)
716   {
717      case 1:
718      case 3:
719         m_vC1 += ((m_v[inp1] - m_vC1) * m_exp[inp1]);
720         v_out = m_vC1;
721         break;
722   }
723
724   /* clip output */
725   if (v_out > m_max_out) v_out = m_max_out;
726   if (v_out < 0) v_out = 0;
727   set_output(0, v_out);
728}
729
730DISCRETE_RESET( dst_rcdisc4)
731{
732   double  v, i, r, rT;
733
734   m_type = 0;
735   /* some error checking. */
736   if (DST_RCDISC4__R1 <= 0 || DST_RCDISC4__R2 <= 0 || DST_RCDISC4__C1 <= 0 || (DST_RCDISC4__R3 <= 0 &&  m_type == 1))
737   {
738      m_device->discrete_log("Invalid component values in NODE_%d.\n", this->index());
739      return;
740   }
741   if (DST_RCDISC4__VP < 3)
742   {
743      m_device->discrete_log("vP must be >= 3V in NODE_%d.\n", this->index());
744      return;
745   }
746   if (DST_RCDISC4__TYPE < 1 || DST_RCDISC4__TYPE > 3)
747   {
748      m_device->discrete_log("Invalid circuit type in NODE_%d.\n", this->index());
749      return;
750   }
751
752   m_vC1 = 0;
753   /* store type as integer */
754   m_type = (int)DST_RCDISC4__TYPE;
755   /* setup the maximum op-amp output. */
756   m_max_out = DST_RCDISC4__VP - OP_AMP_VP_RAIL_OFFSET;
757
758   switch (m_type)
759   {
760      case 1:
761         /* We will simulate this as a voltage divider with 2 states depending
762          * on the input.  But we have to take the diodes into account.
763          */
764         v = DST_RCDISC4__VP - .5;   /* diode drop */
765
766         /* When the input is 1, both R1 & R3 are basically in parallel. */
767         r  = RES_2_PARALLEL(DST_RCDISC4__R1, DST_RCDISC4__R3);
768         rT = DST_RCDISC4__R2 + r;
769         i  = v / rT;
770         m_v[1] = i * r + .5;
771         rT = RES_2_PARALLEL(DST_RCDISC4__R2, r);
772         m_exp[1] = RC_CHARGE_EXP(rT * DST_RCDISC4__C1);
773
774         /* When the input is 0, R1 is out of circuit. */
775         rT = DST_RCDISC4__R2 + DST_RCDISC4__R3;
776         i  = v / rT;
777         m_v[0] = i * DST_RCDISC4__R3 + .5;
778         rT = RES_2_PARALLEL(DST_RCDISC4__R2, DST_RCDISC4__R3);
779         m_exp[0] = RC_CHARGE_EXP(rT * DST_RCDISC4__C1);
780         break;
781
782      case 3:
783         /* We will simulate this as a voltage divider with 2 states depending
784          * on the input.  The 1k pullup is in parallel with the internal TTL
785          * resistance, so we will just use .5k in series with R1.
786          */
787         r = 500.0 + DST_RCDISC4__R1;
788         m_v[1] = RES_VOLTAGE_DIVIDER(r, DST_RCDISC4__R2) * (5.0 - 0.5);
789         rT = RES_2_PARALLEL(r, DST_RCDISC4__R2);
790         m_exp[1] = RC_CHARGE_EXP(rT * DST_RCDISC4__C1);
791
792         /* When the input is 0, R1 is out of circuit. */
793         m_v[0] = 0;
794         m_exp[0] = RC_CHARGE_EXP(DST_RCDISC4__R2 * DST_RCDISC4__C1);
795         break;
796   }
797}
798
799/************************************************************************
800 *
801 * DST_RCDISC5 -  Diode in series with R//C
802 *
803 * input[0]    - Enable input value
804 * input[1]    - input value
805 * input[2]    - Resistor value (initialization only)
806 * input[3]    - Capacitor Value (initialization only)
807 *
808 ************************************************************************/
809#define DST_RCDISC5__ENABLE DISCRETE_INPUT(0)
810#define DST_RCDISC5__IN     DISCRETE_INPUT(1)
811#define DST_RCDISC5__R      DISCRETE_INPUT(2)
812#define DST_RCDISC5__C      DISCRETE_INPUT(3)
813
814DISCRETE_STEP( dst_rcdisc5)
815{
816   double diff,u;
817
818   /* Exponential based in difference between input/output   */
819
820   u = DST_RCDISC5__IN - 0.7; /* Diode drop */
821   if( u < 0)
822      u = 0;
823
824   diff = u - m_v_cap;
825
826   if(DST_RCDISC5__ENABLE)
827   {
828      if(diff < 0)
829         diff = diff * m_exponent0;
830
831      m_v_cap += diff;
832      set_output(0,  m_v_cap);
833   }
834   else
835   {
836      if(diff > 0)
837         m_v_cap = u;
838
839      set_output(0,  0);
840   }
841}
842
843DISCRETE_RESET( dst_rcdisc5)
844{
845   set_output(0,  0);
846
847   m_state = 0;
848   m_t = 0;
849   m_v_cap = 0;
850   m_exponent0 = RC_CHARGE_EXP(DST_RCDISC5__R * DST_RCDISC5__C);
851}
852
853
854/************************************************************************
855 *
856 * DST_RCDISC_MOD -  RC triggered by logic and modulated
857 *
858 * input[0]    - Enable input value
859 * input[1]    - input value 1
860 * input[2]    - input value 2
861 * input[3]    - Resistor 1 value (initialization only)
862 * input[4]    - Resistor 2 value (initialization only)
863 * input[5]    - Resistor 3 value (initialization only)
864 * input[6]    - Resistor 4 value (initialization only)
865 * input[7]    - Capacitor Value (initialization only)
866 * input[8]    - Voltage Value (initialization only)
867 *
868 ************************************************************************/
869#define DST_RCDISC_MOD__IN1     DISCRETE_INPUT(0)
870#define DST_RCDISC_MOD__IN2     DISCRETE_INPUT(1)
871#define DST_RCDISC_MOD__R1      DISCRETE_INPUT(2)
872#define DST_RCDISC_MOD__R2      DISCRETE_INPUT(3)
873#define DST_RCDISC_MOD__R3      DISCRETE_INPUT(4)
874#define DST_RCDISC_MOD__R4      DISCRETE_INPUT(5)
875#define DST_RCDISC_MOD__C       DISCRETE_INPUT(6)
876#define DST_RCDISC_MOD__VP      DISCRETE_INPUT(7)
877
878DISCRETE_STEP(dst_rcdisc_mod)
879{
880   double  diff, v_cap, u, vD;
881   int     mod_state, mod1_state, mod2_state;
882
883   /* Exponential based in difference between input/output   */
884   v_cap = m_v_cap;
885
886   mod1_state = DST_RCDISC_MOD__IN1 > 0.5;
887   mod2_state = DST_RCDISC_MOD__IN2 > 0.6;
888   mod_state  = (mod2_state << 1) + mod1_state;
889
890   u = mod1_state ? 0 : DST_RCDISC_MOD__VP;
891   /* Clamp */
892   diff = u - v_cap;
893   vD = diff * m_vd_gain[mod_state];
894   if (vD < -0.6)
895   {
896      diff  = u + 0.6 - v_cap;
897      diff -= diff * m_exp_low[mod1_state];
898      v_cap += diff;
899      set_output(0,  mod2_state ? 0 : -0.6);
900   }
901   else
902   {
903      diff  -= diff * m_exp_high[mod_state];
904      v_cap += diff;
905      /* neglecting current through R3 drawn by next8 node */
906      set_output(0,  mod2_state ? 0: (u - v_cap) * m_gain[mod1_state]);
907   }
908   m_v_cap = v_cap;
909}
910
911DISCRETE_RESET(dst_rcdisc_mod)
912{
913   double  rc[2], rc2[2];
914
915   /* pre-calculate fixed values */
916   /* DST_RCDISC_MOD__IN1 <= 0.5 */
917   rc[0] = DST_RCDISC_MOD__R1 + DST_RCDISC_MOD__R2;
918   if (rc[0] < 1) rc[0] = 1;
919   m_exp_low[0]  = RC_DISCHARGE_EXP(DST_RCDISC_MOD__C * rc[0]);
920   m_gain[0]     = RES_VOLTAGE_DIVIDER(rc[0], DST_RCDISC_MOD__R4);
921   /* DST_RCDISC_MOD__IN1 > 0.5 */
922   rc[1] = DST_RCDISC_MOD__R2;
923   if (rc[1] < 1) rc[1] = 1;
924   m_exp_low[1]  = RC_DISCHARGE_EXP(DST_RCDISC_MOD__C * rc[1]);
925   m_gain[1]     = RES_VOLTAGE_DIVIDER(rc[1], DST_RCDISC_MOD__R4);
926   /* DST_RCDISC_MOD__IN2 <= 0.6 */
927   rc2[0] = DST_RCDISC_MOD__R4;
928   /* DST_RCDISC_MOD__IN2 > 0.6 */
929   rc2[1] = RES_2_PARALLEL(DST_RCDISC_MOD__R3, DST_RCDISC_MOD__R4);
930   /* DST_RCDISC_MOD__IN1 <= 0.5 && DST_RCDISC_MOD__IN2 <= 0.6 */
931   m_exp_high[0] = RC_DISCHARGE_EXP(DST_RCDISC_MOD__C * (rc[0] + rc2[0]));
932   m_vd_gain[0]  = RES_VOLTAGE_DIVIDER(rc[0], rc2[0]);
933   /* DST_RCDISC_MOD__IN1 > 0.5  && DST_RCDISC_MOD__IN2 <= 0.6 */
934   m_exp_high[1] = RC_DISCHARGE_EXP(DST_RCDISC_MOD__C * (rc[1] + rc2[0]));
935   m_vd_gain[1]  = RES_VOLTAGE_DIVIDER(rc[1], rc2[0]);
936   /* DST_RCDISC_MOD__IN1 <= 0.5 && DST_RCDISC_MOD__IN2 > 0.6 */
937   m_exp_high[2] = RC_DISCHARGE_EXP(DST_RCDISC_MOD__C * (rc[0] + rc2[1]));
938   m_vd_gain[2]  = RES_VOLTAGE_DIVIDER(rc[0], rc2[1]);
939   /* DST_RCDISC_MOD__IN1 > 0.5  && DST_RCDISC_MOD__IN2 > 0.6 */
940   m_exp_high[3] = RC_DISCHARGE_EXP(DST_RCDISC_MOD__C * (rc[1] + rc2[1]));
941   m_vd_gain[3]  = RES_VOLTAGE_DIVIDER(rc[1], rc2[1]);
942
943   m_v_cap  = 0;
944   set_output(0,  0);
945}
946
947/************************************************************************
948 *
949 * DST_RCFILTER - Usage of node_description values for RC filter
950 *
951 * input[0]    - Enable input value
952 * input[1]    - input value
953 * input[2]    - Resistor value (initialization only)
954 * input[3]    - Capacitor Value (initialization only)
955 * input[4]    - Voltage reference. Usually 0V.
956 *
957 ************************************************************************/
958#define DST_RCFILTER__VIN       DISCRETE_INPUT(0)
959#define DST_RCFILTER__R         DISCRETE_INPUT(1)
960#define DST_RCFILTER__C         DISCRETE_INPUT(2)
961#define DST_RCFILTER__VREF      DISCRETE_INPUT(3)
962
963DISCRETE_STEP(dst_rcfilter)
964{
965   if (EXPECTED(m_is_fast))
966      m_v_out += ((DST_RCFILTER__VIN - m_v_out) * m_exponent);
967   else
968   {
969      if (UNEXPECTED(m_has_rc_nodes))
970      {
971         double rc = DST_RCFILTER__R * DST_RCFILTER__C;
972         if (rc != m_rc)
973         {
974            m_rc = rc;
975            m_exponent = RC_CHARGE_EXP(rc);
976         }
977      }
978
979      /************************************************************************/
980      /* Next Value = PREV + (INPUT_VALUE - PREV)*(1-(EXP(-TIMEDELTA/RC)))    */
981      /************************************************************************/
982
983      m_vCap += ((DST_RCFILTER__VIN - m_v_out) * m_exponent);
984      m_v_out = m_vCap + DST_RCFILTER__VREF;
985   }
986   set_output(0,  m_v_out);
987}
988
989
990DISCRETE_RESET(dst_rcfilter)
991{
992   m_has_rc_nodes = this->input_is_node() & 0x6;
993   m_rc = DST_RCFILTER__R * DST_RCFILTER__C;
994   m_exponent = RC_CHARGE_EXP(m_rc);
995   m_vCap   = 0;
996   m_v_out = 0;
997   /* FIXME --> we really need another class here */
998   if (!m_has_rc_nodes && DST_RCFILTER__VREF == 0)
999      m_is_fast = 1;
1000   else
1001      m_is_fast = 0;
1002}
1003
1004/************************************************************************
1005 *
1006 * DST_RCFILTER_SW - Usage of node_description values for switchable RC filter
1007 *
1008 * input[0]    - Enable input value
1009 * input[1]    - input value
1010 * input[2]    - Resistor value (initialization only)
1011 * input[3]    - Capacitor Value (initialization only)
1012 * input[4]    - Voltage reference. Usually 0V.
1013 *
1014 ************************************************************************/
1015#define DST_RCFILTER_SW__ENABLE     DISCRETE_INPUT(0)
1016#define DST_RCFILTER_SW__VIN        DISCRETE_INPUT(1)
1017#define DST_RCFILTER_SW__SWITCH     DISCRETE_INPUT(2)
1018#define DST_RCFILTER_SW__R          DISCRETE_INPUT(3)
1019#define DST_RCFILTER_SW__C(x)       DISCRETE_INPUT(4+x)
1020
1021/* 74HC4066 : 15
1022 * 74VHC4066 : 15
1023 * UTC4066 : 270 @ 5VCC, 80 @ 15VCC
1024 * CD4066BC : 270 (Fairchild)
1025 *
1026 * The choice below makes scramble sound about "right". For future error reports,
1027 * we need the exact type of switch and at which voltage (5, 12?) it is operated.
1028 */
1029#define CD4066_ON_RES (40)
1030
1031// FIXME: This needs optimization !
1032DISCRETE_STEP(dst_rcfilter_sw)
1033{
1034   int i;
1035   int bits = (int)DST_RCFILTER_SW__SWITCH;
1036   double us = 0;
1037   double vIn = DST_RCFILTER_SW__VIN;
1038   double v_out;
1039
1040   if (EXPECTED(DST_RCFILTER_SW__ENABLE))
1041   {
1042      switch (bits)
1043      {
1044      case 0:
1045         v_out = vIn;
1046         break;
1047      case 1:
1048         m_vCap[0] += (vIn - m_vCap[0]) * m_exp0;
1049         v_out = m_vCap[0] + (vIn - m_vCap[0]) * m_factor;
1050         break;
1051      case 2:
1052         m_vCap[1] += (vIn - m_vCap[1]) * m_exp1;
1053         v_out = m_vCap[1] + (vIn - m_vCap[1]) * m_factor;
1054         break;
1055      default:
1056         for (i = 0; i < 4; i++)
1057         {
1058            if (( bits & (1 << i)) != 0)
1059               us += m_vCap[i];
1060         }
1061         v_out = m_f1[bits] * vIn + m_f2[bits]  * us;
1062         for (i = 0; i < 4; i++)
1063         {
1064            if (( bits & (1 << i)) != 0)
1065               m_vCap[i] += (v_out - m_vCap[i]) * m_exp[i];
1066         }
1067      }
1068      set_output(0, v_out);
1069   }
1070   else
1071   {
1072      set_output(0, 0);
1073   }
1074}
1075
1076DISCRETE_RESET(dst_rcfilter_sw)
1077{
1078   int i, bits;
1079
1080   for (i = 0; i < 4; i++)
1081   {
1082      m_vCap[i] = 0;
1083      m_exp[i] = RC_CHARGE_EXP( CD4066_ON_RES * DST_RCFILTER_SW__C(i));
1084   }
1085
1086   for (bits=0; bits < 15; bits++)
1087   {
1088      double rs = 0;
1089
1090      for (i = 0; i < 4; i++)
1091      {
1092         if (( bits & (1 << i)) != 0)
1093            rs += DST_RCFILTER_SW__R;
1094      }
1095      m_f1[bits] = RES_VOLTAGE_DIVIDER(rs, CD4066_ON_RES);
1096      m_f2[bits] = DST_RCFILTER_SW__R / (CD4066_ON_RES + rs);
1097   }
1098
1099
1100   /* fast cases */
1101   m_exp0 = RC_CHARGE_EXP((CD4066_ON_RES + DST_RCFILTER_SW__R) * DST_RCFILTER_SW__C(0));
1102   m_exp1 = RC_CHARGE_EXP((CD4066_ON_RES + DST_RCFILTER_SW__R) * DST_RCFILTER_SW__C(1));
1103   m_factor = RES_VOLTAGE_DIVIDER(DST_RCFILTER_SW__R, CD4066_ON_RES);
1104
1105   set_output(0,  0);
1106}
1107
1108
1109/************************************************************************
1110 *
1111 * DST_RCINTEGRATE - Two diode inputs, transistor and a R/C charge
1112 *                   discharge network
1113 *
1114 * input[0]    - Enable input value
1115 * input[1]    - input value 1
1116 * input[2]    - input value 2
1117 * input[3]    - Resistor 1 value (initialization only)
1118 * input[4]    - Resistor 2 value (initialization only)
1119 * input[5]    - Capacitor Value (initialization only)
1120 *
1121 ************************************************************************/
1122#define DST_RCINTEGRATE__IN1    DISCRETE_INPUT(0)
1123#define DST_RCINTEGRATE__R1     DISCRETE_INPUT(1)
1124#define DST_RCINTEGRATE__R2     DISCRETE_INPUT(2)
1125#define DST_RCINTEGRATE__R3     DISCRETE_INPUT(3)
1126#define DST_RCINTEGRATE__C      DISCRETE_INPUT(4)
1127#define DST_RCINTEGRATE__VP     DISCRETE_INPUT(5)
1128#define DST_RCINTEGRATE__TYPE   DISCRETE_INPUT(6)
1129
1130/* Ebers-Moll large signal model
1131 * Couriersud:
1132 * The implementation avoids all iterative approaches in order not to burn cycles
1133 * We will calculate Ic from vBE and use this as an indication where to go.
1134 * The implementation may oscillate if you change the weighting factors at the
1135 * end.
1136 *
1137 * This implementation is not perfect, but does it's job in dkong'
1138 */
1139
1140/* reverse saturation current */
1141#define IES     7e-15
1142#define ALPHAT  0.99
1143#define KT      0.026
1144#define EM_IC(x) (ALPHAT * IES * exp( (x) / KT - 1.0 ))
1145
1146DISCRETE_STEP( dst_rcintegrate)
1147{
1148   double diff, u, iQ, iQc, iC, RG, vE;
1149   double vP;
1150
1151   u  = DST_RCINTEGRATE__IN1;
1152   vP = DST_RCINTEGRATE__VP;
1153
1154   if ( u - 0.7  < m_vCap * m_gain_r1_r2)
1155   {
1156      /* discharge .... */
1157      diff  = 0.0 - m_vCap;
1158      iC    = m_c_exp1 * diff; /* iC */
1159      diff -= diff * m_exp_exponent1;
1160      m_vCap += diff;
1161      iQ = 0;
1162      vE = m_vCap * m_gain_r1_r2;
1163      RG = vE / iC;
1164   }
1165   else
1166   {
1167      /* charging */
1168      diff  = (vP - m_vCE) * m_f - m_vCap;
1169      iC    = 0.0 - m_c_exp0 * diff; /* iC */
1170      diff -= diff * m_exp_exponent0;
1171      m_vCap += diff;
1172      iQ = iC + (iC * DST_RCINTEGRATE__R1 + m_vCap) / DST_RCINTEGRATE__R2;
1173      RG = (vP - m_vCE) / iQ;
1174      vE = (RG - DST_RCINTEGRATE__R3) / RG * (vP - m_vCE);
1175   }
1176
1177
1178   u = DST_RCINTEGRATE__IN1;
1179   if (u > 0.7 + vE)
1180   {
1181      vE = u - 0.7;
1182      //iQc = EM_IC(u - vE);
1183      iQc = m_EM_IC_0_7;
1184   }
1185   else
1186      iQc = EM_IC(u - vE);
1187
1188   m_vCE = MIN(vP - 0.1, vP - RG * iQc);
1189
1190   /* Avoid oscillations
1191    * The method tends to largely overshoot - no wonder without
1192    * iterative solution approximation
1193    */
1194
1195   m_vCE = MAX(m_vCE, 0.1 );
1196   m_vCE = 0.1 * m_vCE + 0.9 * (vP - vE - iQ * DST_RCINTEGRATE__R3);
1197
1198   switch (m_type)
1199   {
1200      case DISC_RC_INTEGRATE_TYPE1:
1201         set_output(0,  m_vCap);
1202         break;
1203      case DISC_RC_INTEGRATE_TYPE2:
1204         set_output(0,  vE);
1205         break;
1206      case DISC_RC_INTEGRATE_TYPE3:
1207         set_output(0,  MAX(0, vP - iQ * DST_RCINTEGRATE__R3));
1208         break;
1209   }
1210}
1211
1212DISCRETE_RESET(dst_rcintegrate)
1213{
1214   double r;
1215   double dt = this->sample_time();
1216
1217   m_type = DST_RCINTEGRATE__TYPE;
1218
1219   m_vCap = 0;
1220   m_vCE  = 0;
1221
1222   /* pre-calculate fixed values */
1223   m_gain_r1_r2 = RES_VOLTAGE_DIVIDER(DST_RCINTEGRATE__R1, DST_RCINTEGRATE__R2);
1224
1225   r = DST_RCINTEGRATE__R1 / DST_RCINTEGRATE__R2 * DST_RCINTEGRATE__R3 + DST_RCINTEGRATE__R1 + DST_RCINTEGRATE__R3;
1226
1227   m_f = RES_VOLTAGE_DIVIDER(DST_RCINTEGRATE__R3, DST_RCINTEGRATE__R2);
1228   m_exponent0 = -1.0 * r * m_f * DST_RCINTEGRATE__C;
1229   m_exponent1 = -1.0 * (DST_RCINTEGRATE__R1 + DST_RCINTEGRATE__R2) * DST_RCINTEGRATE__C;
1230   m_exp_exponent0 = exp(dt / m_exponent0);
1231   m_exp_exponent1 = exp(dt / m_exponent1);
1232   m_c_exp0 =  DST_RCINTEGRATE__C / m_exponent0 * m_exp_exponent0;
1233   m_c_exp1 =  DST_RCINTEGRATE__C / m_exponent1 * m_exp_exponent1;
1234
1235   m_EM_IC_0_7 = EM_IC(0.7);
1236
1237   set_output(0,  0);
1238}
1239
1240/************************************************************************
1241 *
1242 * DST_SALLEN_KEY - Sallen-Key filter circuit
1243 *
1244 * input[0]    - Enable input value
1245 * input[1]    - IN0 node
1246 * input[3]    - Filter Type
1247 *
1248 * also passed discrete_op_amp_filt_info structure
1249 *
1250 * 2008, couriersud
1251 ************************************************************************/
1252#define DST_SALLEN_KEY__ENABLE  DISCRETE_INPUT(0)
1253#define DST_SALLEN_KEY__INP0    DISCRETE_INPUT(1)
1254#define DST_SALLEN_KEY__TYPE    DISCRETE_INPUT(2)
1255
1256DISCRETE_STEP(dst_sallen_key)
1257{
1258   double gain = 1.0;
1259   double v_out;
1260
1261   if (DST_SALLEN_KEY__ENABLE == 0.0)
1262   {
1263      gain = 0.0;
1264   }
1265
1266   v_out = -m_fc.a1 * m_fc.y1 - m_fc.a2 * m_fc.y2 +
1267               m_fc.b0 * gain * DST_SALLEN_KEY__INP0 + m_fc.b1 * m_fc.x1 + m_fc.b2 * m_fc.x2;
1268
1269   m_fc.x2 = m_fc.x1;
1270   m_fc.x1 = gain * DST_SALLEN_KEY__INP0;
1271   m_fc.y2 = m_fc.y1;
1272   m_fc.y1 = v_out;
1273   set_output(0, v_out);
1274}
1275
1276DISCRETE_RESET(dst_sallen_key)
1277{
1278   DISCRETE_DECLARE_INFO(discrete_op_amp_filt_info)
1279
1280   double freq, q;
1281
1282   switch ((int) DST_SALLEN_KEY__TYPE)
1283   {
1284      case DISC_SALLEN_KEY_LOW_PASS:
1285         freq = 1.0 / ( 2.0 * M_PI * sqrt(info->c1 * info->c2 * info->r1 * info->r2));
1286         q = sqrt(info->c1 * info->c2 * info->r1 * info->r2) / (info->c2 * (info->r1 + info->r2));
1287         break;
1288      default:
1289         fatalerror("Unknown sallen key filter type\n");
1290   }
1291
1292   calculate_filter2_coefficients(this, freq, 1.0 / q, DISC_FILTER_LOWPASS, m_fc);
1293   set_output(0,  0);
1294}
1295
1296
1297/* !!!!!!!!!!! NEW FILTERS for testing !!!!!!!!!!!!!!!!!!!!! */
1298
1299
1300/************************************************************************
1301 *
1302 * DST_RCFILTERN - Usage of node_description values for RC filter
1303 *
1304 * input[0]    - Enable input value
1305 * input[1]    - input value
1306 * input[2]    - Resistor value (initialization only)
1307 * input[3]    - Capacitor Value (initialization only)
1308 *
1309 ************************************************************************/
1310#define DST_RCFILTERN__ENABLE       DISCRETE_INPUT(0)
1311#define DST_RCFILTERN__IN       DISCRETE_INPUT(1)
1312#define DST_RCFILTERN__R        DISCRETE_INPUT(2)
1313#define DST_RCFILTERN__C        DISCRETE_INPUT(3)
1314
1315#if 0
1316DISCRETE_RESET(dst_rcfilterN)
1317{
1318#if 0
1319   double f=1.0/(2*M_PI* DST_RCFILTERN__R * DST_RCFILTERN__C);
1320
1321/* !!!!!!!!!!!!!! CAN'T CHEAT LIKE THIS !!!!!!!!!!!!!!!! */
1322/* Put this stuff in a context */
1323
1324   this->m_input[2] = f;
1325   this->m_input[3] = DISC_FILTER_LOWPASS;
1326
1327   /* Use first order filter */
1328   dst_filter1_reset(node);
1329#endif
1330}
1331#endif
1332
1333/************************************************************************
1334 *
1335 * DST_RCDISCN -   Usage of node_description values for RC discharge
1336 *                (inverse slope of DST_RCFILTER)
1337 *
1338 * input[0]    - Enable input value
1339 * input[1]    - input value
1340 * input[2]    - Resistor value (initialization only)
1341 * input[3]    - Capacitor Value (initialization only)
1342 *
1343 ************************************************************************/
1344#define DST_RCDISCN__ENABLE DISCRETE_INPUT(0)
1345#define DST_RCDISCN__IN     DISCRETE_INPUT(1)
1346#define DST_RCDISCN__R      DISCRETE_INPUT(2)
1347#define DST_RCDISCN__C      DISCRETE_INPUT(3)
1348
1349DISCRETE_RESET(dst_rcdiscN)
1350{
1351#if 0
1352   double f = 1.0 / (2 * M_PI * DST_RCDISCN__R * DST_RCDISCN__C);
1353
1354/* !!!!!!!!!!!!!! CAN'T CHEAT LIKE THIS !!!!!!!!!!!!!!!! */
1355/* Put this stuff in a context */
1356
1357   this->m_input[2] = f;
1358   this->m_input[3] = DISC_FILTER_LOWPASS;
1359
1360   /* Use first order filter */
1361   dst_filter1_reset(node);
1362#endif
1363}
1364
1365DISCRETE_STEP(dst_rcdiscN)
1366{
1367   double gain = 1.0;
1368   double v_out;
1369
1370   if (DST_RCDISCN__ENABLE == 0.0)
1371   {
1372      gain = 0.0;
1373   }
1374
1375   /* A rise in the input signal results in an instant charge, */
1376   /* else discharge through the RC to zero */
1377   if (gain* DST_RCDISCN__IN > m_x1)
1378      v_out = gain* DST_RCDISCN__IN;
1379   else
1380      v_out = -m_a1*m_y1;
1381
1382   m_x1 = gain* DST_RCDISCN__IN;
1383   m_y1 = v_out;
1384   set_output(0, v_out);
1385}
1386
1387
1388/************************************************************************
1389 *
1390 * DST_RCDISC2N -  Usage of node_description values for RC discharge
1391 *                Has switchable charge resistor/input
1392 *
1393 * input[0]    - Switch input value
1394 * input[1]    - input[0] value
1395 * input[2]    - Resistor0 value (initialization only)
1396 * input[3]    - input[1] value
1397 * input[4]    - Resistor1 value (initialization only)
1398 * input[5]    - Capacitor Value (initialization only)
1399 *
1400 ************************************************************************/
1401#define DST_RCDISC2N__ENABLE    DISCRETE_INPUT(0)
1402#define DST_RCDISC2N__IN0       DISCRETE_INPUT(1)
1403#define DST_RCDISC2N__R0        DISCRETE_INPUT(2)
1404#define DST_RCDISC2N__IN1       DISCRETE_INPUT(3)
1405#define DST_RCDISC2N__R1        DISCRETE_INPUT(4)
1406#define DST_RCDISC2N__C         DISCRETE_INPUT(5)
1407
1408
1409DISCRETE_STEP(dst_rcdisc2N)
1410{
1411   double inp = ((DST_RCDISC2N__ENABLE == 0) ? DST_RCDISC2N__IN0 : DST_RCDISC2N__IN1);
1412   double v_out;
1413
1414   if (DST_RCDISC2N__ENABLE == 0)
1415      v_out = -m_fc0.a1*m_y1 + m_fc0.b0*inp + m_fc0.b1 * m_x1;
1416   else
1417      v_out = -m_fc1.a1*m_y1 + m_fc1.b0*inp + m_fc1.b1*m_x1;
1418
1419   m_x1 = inp;
1420   m_y1 = v_out;
1421   set_output(0, v_out);
1422}
1423
1424DISCRETE_RESET(dst_rcdisc2N)
1425{
1426   double f1,f2;
1427
1428   f1 = 1.0 / (2 * M_PI * DST_RCDISC2N__R0 * DST_RCDISC2N__C);
1429   f2 = 1.0 / (2 * M_PI * DST_RCDISC2N__R1 * DST_RCDISC2N__C);
1430
1431   calculate_filter1_coefficients(this, f1, DISC_FILTER_LOWPASS, m_fc0);
1432   calculate_filter1_coefficients(this, f2, DISC_FILTER_LOWPASS, m_fc1);
1433
1434   /* Initialize the object */
1435   set_output(0,  0);
1436}
trunk/src/emu/sound/sound.mak
r28731r28732
6161
6262$(SOUNDOBJ)/discrete.o: $(SOUNDSRC)/discrete.c \
6363                  $(SOUNDSRC)/discrete.h \
64                  $(SOUNDSRC)/disc_dev.c \
65                  $(SOUNDSRC)/disc_sys.c \
66                  $(SOUNDSRC)/disc_flt.c \
67                  $(SOUNDSRC)/disc_inp.c \
68                  $(SOUNDSRC)/disc_mth.c \
69                  $(SOUNDSRC)/disc_wav.c
64                  $(SOUNDSRC)/disc_dev.inc \
65                  $(SOUNDSRC)/disc_sys.inc \
66                  $(SOUNDSRC)/disc_flt.inc \
67                  $(SOUNDSRC)/disc_inp.inc \
68                  $(SOUNDSRC)/disc_mth.inc \
69                  $(SOUNDSRC)/disc_wav.inc
7070
7171
7272#-------------------------------------------------
trunk/src/emu/sound/disc_sys.inc
r0r28732
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 *  (c) D.Renaud 2003-2004
9 *
10 ************************************************************************
11 *
12 * DSO_OUTPUT            - Output node
13 * DSO_TASK              - Task node
14 *
15 * Task and list routines
16 *
17 ************************************************************************/
18
19
20
21
22/*************************************
23 *
24 *  Task node (main task execution)
25 *
26 *************************************/
27
28
29DISCRETE_START( dso_csvlog )
30{
31   int log_num, node_num;
32
33   log_num = m_device->same_module_index(*this);
34   m_sample_num = 0;
35
36   sprintf(m_name, "discrete_%s_%d.csv", m_device->tag(), log_num);
37   m_csv_file = fopen(m_name, "w");
38   /* Output some header info */
39   fprintf(m_csv_file, "\"MAME Discrete System Node Log\"\n");
40   fprintf(m_csv_file, "\"Log Version\", 1.0\n");
41   fprintf(m_csv_file, "\"Sample Rate\", %d\n", this->sample_rate());
42   fprintf(m_csv_file, "\n");
43   fprintf(m_csv_file, "\"Sample\"");
44   for (node_num = 0; node_num < this->active_inputs(); node_num++)
45   {
46      fprintf(m_csv_file, ", \"NODE_%2d\"", NODE_INDEX(this->input_node(node_num)));
47   }
48   fprintf(m_csv_file, "\n");
49}
50
51DISCRETE_STOP( dso_csvlog )
52{
53   /* close any csv files */
54   if (m_csv_file)
55      fclose(m_csv_file);
56}
57
58DISCRETE_STEP( dso_csvlog )
59{
60   int nodenum;
61
62   /* Dump any csv logs */
63   fprintf(m_csv_file, "%" I64FMT "d", ++m_sample_num);
64   for (nodenum = 0; nodenum < this->active_inputs(); nodenum++)
65   {
66      fprintf(m_csv_file, ", %f", *this->m_input[nodenum]);
67   }
68   fprintf(m_csv_file, "\n");
69}
70
71DISCRETE_RESET( dso_csvlog )
72{
73   this->step();
74}
75
76
77DISCRETE_START( dso_wavlog )
78{
79   int log_num;
80
81   log_num = m_device->same_module_index(*this);
82   sprintf(m_name, "discrete_%s_%d.wav", m_device->tag(), log_num);
83   m_wavfile = wav_open(m_name, sample_rate(), active_inputs()/2);
84}
85
86DISCRETE_STOP( dso_wavlog )
87{
88   /* close any wave files */
89   if (m_wavfile)
90      wav_close(m_wavfile);
91}
92
93DISCRETE_STEP( dso_wavlog )
94{
95   double val;
96   INT16 wave_data_l, wave_data_r;
97
98   /* Dump any wave logs */
99   /* get nodes to be logged and apply gain, then clip to 16 bit */
100   val = DISCRETE_INPUT(0) * DISCRETE_INPUT(1);
101   val = (val < -32768) ? -32768 : (val > 32767) ? 32767 : val;
102   wave_data_l = (INT16)val;
103   if (this->active_inputs() == 2)
104   {
105      /* DISCRETE_WAVLOG1 */
106      wav_add_data_16(m_wavfile, &wave_data_l, 1);
107   }
108   else
109   {
110      /* DISCRETE_WAVLOG2 */
111      val = DISCRETE_INPUT(2) * DISCRETE_INPUT(3);
112      val = (val < -32768) ? -32768 : (val > 32767) ? 32767 : val;
113      wave_data_r = (INT16)val;
114
115      wav_add_data_16lr(m_wavfile, &wave_data_l, &wave_data_r, 1);
116   }
117}
118
119DISCRETE_RESET( dso_wavlog )
120{
121   this->step();
122}
Property changes on: trunk/src/emu/sound/disc_sys.inc
Added: svn:mime-type
   + text/plain
Added: svn:eol-style
   + native
trunk/src/emu/sound/disc_inp.inc
r0r28732
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 * DSS_ADJUSTMENT        - UI Mapped adjustable input
12 * DSS_CONSTANT          - Node based constant - Do we need this ???
13 * DSS_INPUT_x           - Input devices
14 * DSS_INPUT_STREAM      - Connects external streams to the discrete system
15 *
16 ************************************************************************/
17
18
19#define DSS_INPUT__GAIN     DISCRETE_INPUT(0)
20#define DSS_INPUT__OFFSET   DISCRETE_INPUT(1)
21#define DSS_INPUT__INIT     DISCRETE_INPUT(2)
22
23READ8_DEVICE_HANDLER(discrete_sound_r)
24{
25   discrete_device *disc_device = downcast<discrete_device *>(device);
26   return  disc_device->read( space, offset, 0xff);
27}
28
29
30WRITE8_DEVICE_HANDLER(discrete_sound_w)
31{
32   discrete_device *disc_device = downcast<discrete_device *>(device);
33   disc_device->write(space, offset, data, 0xff);
34}
35
36/************************************************************************
37 *
38 * DSS_ADJUSTMENT - UI Adjustable constant node to emulate trimmers
39 *
40 * input[0]    - Enable
41 * input[1]    - Minimum value
42 * input[2]    - Maximum value
43 * input[3]    - Log/Linear 0=Linear !0=Log
44 * input[4]    - Input Port number
45 * input[5]    -
46 * input[6]    -
47 *
48 ************************************************************************/
49#define DSS_ADJUSTMENT__MIN     DISCRETE_INPUT(0)
50#define DSS_ADJUSTMENT__MAX     DISCRETE_INPUT(1)
51#define DSS_ADJUSTMENT__LOG     DISCRETE_INPUT(2)
52#define DSS_ADJUSTMENT__PORT    DISCRETE_INPUT(3)
53#define DSS_ADJUSTMENT__PMIN    DISCRETE_INPUT(4)
54#define DSS_ADJUSTMENT__PMAX    DISCRETE_INPUT(5)
55
56DISCRETE_STEP(dss_adjustment)
57{
58   INT32  rawportval = m_port->read();
59
60   /* only recompute if the value changed from last time */
61   if (UNEXPECTED(rawportval != m_lastpval))
62   {
63      double portval   = (double)(rawportval - m_pmin) * m_pscale;
64      double scaledval = portval * m_scale + m_min;
65
66      m_lastpval = rawportval;
67      if (DSS_ADJUSTMENT__LOG == 0)
68         set_output(0,  scaledval);
69      else
70         set_output(0,  pow(10, scaledval));
71   }
72}
73
74DISCRETE_RESET(dss_adjustment)
75{
76   double min, max;
77
78   astring fulltag;
79   m_port = m_device->machine().root_device().ioport(m_device->siblingtag(fulltag, (const char *)this->custom_data()).cstr());
80   if (m_port == NULL)
81      fatalerror("DISCRETE_ADJUSTMENT - NODE_%d has invalid tag\n", this->index());
82
83   m_lastpval = 0x7fffffff;
84   m_pmin     = DSS_ADJUSTMENT__PMIN;
85   m_pscale   = 1.0 / (double)(DSS_ADJUSTMENT__PMAX - DSS_ADJUSTMENT__PMIN);
86
87   /* linear scale */
88   if (DSS_ADJUSTMENT__LOG == 0)
89   {
90      m_min   = DSS_ADJUSTMENT__MIN;
91      m_scale = DSS_ADJUSTMENT__MAX - DSS_ADJUSTMENT__MIN;
92   }
93
94   /* logarithmic scale */
95   else
96   {
97      /* force minimum and maximum to be > 0 */
98      min = (DSS_ADJUSTMENT__MIN > 0) ? DSS_ADJUSTMENT__MIN : 1;
99      max = (DSS_ADJUSTMENT__MAX > 0) ? DSS_ADJUSTMENT__MAX : 1;
100      m_min   = log10(min);
101      m_scale = log10(max) - log10(min);
102   }
103
104   this->step();
105}
106
107
108/************************************************************************
109 *
110 * DSS_CONSTANT - This is a constant.
111 *
112 * input[0]    - Constant value
113 *
114 ************************************************************************/
115#define DSS_CONSTANT__INIT  DISCRETE_INPUT(0)
116
117DISCRETE_RESET(dss_constant)
118{
119   set_output(0, DSS_CONSTANT__INIT);
120}
121
122
123/************************************************************************
124 *
125 * DSS_INPUT_x    - Receives input from discrete_sound_w
126 *
127 * input[0]    - Gain value
128 * input[1]    - Offset value
129 * input[2]    - Starting Position
130 * input[3]    - Current data value
131 *
132 ************************************************************************/
133
134DISCRETE_RESET(dss_input_data)
135{
136   m_gain = DSS_INPUT__GAIN;
137   m_offset = DSS_INPUT__OFFSET;
138
139   m_data = DSS_INPUT__INIT;
140   set_output(0,  m_data * m_gain + m_offset);
141}
142
143void DISCRETE_CLASS_FUNC(dss_input_data, input_write)(int sub_node, UINT8 data )
144{
145   UINT8 new_data    = 0;
146
147   new_data = data;
148
149   if (m_data != new_data)
150   {
151      /* Bring the system up to now */
152      m_device->update_to_current_time();
153
154      m_data = new_data;
155
156      /* Update the node output here so we don't have to do it each step */
157      set_output(0,  m_data * m_gain + m_offset);
158   }
159}
160
161DISCRETE_RESET(dss_input_logic)
162{
163   m_gain = DSS_INPUT__GAIN;
164   m_offset = DSS_INPUT__OFFSET;
165
166   m_data = (DSS_INPUT__INIT == 0) ? 0 : 1;
167   set_output(0,  m_data * m_gain + m_offset);
168}
169
170void DISCRETE_CLASS_FUNC(dss_input_logic, input_write)(int sub_node, UINT8 data )
171{
172   UINT8 new_data    = 0;
173
174   new_data =  data ? 1 : 0;
175
176   if (m_data != new_data)
177   {
178      /* Bring the system up to now */
179      m_device->update_to_current_time();
180
181      m_data = new_data;
182
183      /* Update the node output here so we don't have to do it each step */
184      set_output(0,  m_data * m_gain + m_offset);
185   }
186}
187
188DISCRETE_RESET(dss_input_not)
189{
190   m_gain = DSS_INPUT__GAIN;
191   m_offset = DSS_INPUT__OFFSET;
192
193   m_data = (DSS_INPUT__INIT == 0) ? 1 : 0;
194   set_output(0,  m_data * m_gain + m_offset);
195}
196
197void DISCRETE_CLASS_FUNC(dss_input_not, input_write)(int sub_node, UINT8 data )
198{
199   UINT8 new_data    = 0;
200
201   new_data = data ? 0 : 1;
202
203   if (m_data != new_data)
204   {
205      /* Bring the system up to now */
206      m_device->update_to_current_time();
207
208      m_data = new_data;
209
210      /* Update the node output here so we don't have to do it each step */
211      set_output(0,  m_data * m_gain + m_offset);
212   }
213}
214
215DISCRETE_STEP(dss_input_pulse)
216{
217   /* Set a valid output */
218   set_output(0,  m_data);
219   /* Reset the input to default for the next cycle */
220   /* node order is now important */
221   m_data = DSS_INPUT__INIT;
222}
223
224DISCRETE_RESET(dss_input_pulse)
225{
226   m_data = (DSS_INPUT__INIT == 0) ? 0 : 1;
227   set_output(0,  m_data);
228}
229
230void DISCRETE_CLASS_FUNC(dss_input_pulse, input_write)(int sub_node, UINT8 data )
231{
232   UINT8 new_data    = 0;
233
234   new_data =  data ? 1 : 0;
235
236   if (m_data != new_data)
237   {
238      /* Bring the system up to now */
239      m_device->update_to_current_time();
240      m_data = new_data;
241   }
242}
243
244/************************************************************************
245 *
246 * DSS_INPUT_STREAM    - Receives input from a routed stream
247 *
248 * input[0]    - Input stream number
249 * input[1]    - Gain value
250 * input[2]    - Offset value
251 *
252 ************************************************************************/
253#define DSS_INPUT_STREAM__STREAM    DISCRETE_INPUT(0)
254#define DSS_INPUT_STREAM__GAIN      DISCRETE_INPUT(1)
255#define DSS_INPUT_STREAM__OFFSET    DISCRETE_INPUT(2)
256
257STREAM_UPDATE( discrete_dss_input_stream_node::static_stream_generate )
258{
259   reinterpret_cast<discrete_dss_input_stream_node *>(param)->stream_generate(inputs, outputs, samples);
260}
261
262void discrete_dss_input_stream_node::stream_generate(stream_sample_t **inputs, stream_sample_t **outputs, int samples)
263{
264   stream_sample_t *ptr = outputs[0];
265   int samplenum = samples;
266
267   while (samplenum-- > 0)
268      *(ptr++) = m_data;
269}
270DISCRETE_STEP(dss_input_stream)
271{
272   /* the context pointer is set to point to the current input stream data in discrete_stream_update */
273   if (EXPECTED(m_ptr))
274   {
275      set_output(0,  (*m_ptr) * m_gain + m_offset);
276      m_ptr++;
277   }
278   else
279      set_output(0,  0);
280}
281
282DISCRETE_RESET(dss_input_stream)
283{
284   m_ptr = NULL;
285   m_data = 0;
286}
287
288void DISCRETE_CLASS_FUNC(dss_input_stream, input_write)(int sub_node, UINT8 data )
289{
290   UINT8 new_data    = 0;
291
292   new_data =  data;
293
294   if (m_data != new_data)
295   {
296      if (m_is_buffered)
297      {
298         /* Bring the system up to now */
299         m_buffer_stream->update();
300
301         m_data = new_data;
302      }
303      else
304      {
305         /* Bring the system up to now */
306         m_device->update_to_current_time();
307
308         m_data = new_data;
309
310         /* Update the node output here so we don't have to do it each step */
311         set_output(0,  new_data * m_gain + m_offset);
312      }
313   }
314}
315
316DISCRETE_START(dss_input_stream)
317{
318   discrete_base_node::start();
319
320   /* Stream out number is set during start */
321   m_stream_in_number = DSS_INPUT_STREAM__STREAM;
322   m_gain = DSS_INPUT_STREAM__GAIN;
323   m_offset = DSS_INPUT_STREAM__OFFSET;
324   m_ptr = NULL;
325
326   m_is_buffered = is_buffered();
327   m_buffer_stream = NULL;
328}
329
330void DISCRETE_CLASS_NAME(dss_input_stream)::stream_start(void)
331{
332   if (m_is_buffered)
333   {
334      /* stream_buffered input only supported for sound devices */
335      discrete_sound_device *snd_device = downcast<discrete_sound_device *>(m_device);
336      //assert(DSS_INPUT_STREAM__STREAM < snd_device->m_input_stream_list.count());
337
338      m_buffer_stream = m_device->machine().sound().stream_alloc(*snd_device, 0, 1, this->sample_rate(), this, static_stream_generate);
339
340      snd_device->get_stream()->set_input(m_stream_in_number, m_buffer_stream);
341   }
342}
Property changes on: trunk/src/emu/sound/disc_inp.inc
Added: svn:mime-type
   + text/plain
Added: svn:eol-style
   + native
trunk/src/emu/sound/disc_flt.inc
r0r28732
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_CRFILTER          - Simple CR filter & also highpass filter
12 * DST_FILTER1           - Generic 1st order filter
13 * DST_FILTER2           - Generic 2nd order filter
14 * DST_OP_AMP_FILT       - Op Amp filter circuits
15 * DST_RC_CIRCUIT_1      - RC charge/discharge circuit
16 * DST_RCDISC            - Simple discharging RC
17 * DST_RCDISC2           - Simple charge R1/C, discharge R0/C
18 * DST_RCDISC3           - Simple charge R1/c, discharge R0*R1/(R0+R1)/C
19 * DST_RCDISC4           - Various charge/discharge circuits
20 * DST_RCDISC5           - Diode in series with R//C
21 * DST_RCDISC_MOD        - RC triggered by logic and modulated
22 * DST_RCFILTER          - Simple RC filter & also lowpass filter
23 * DST_RCFILTER_SW       - Usage of node_description values for switchable RC filter
24 * DST_RCINTEGRATE       - Two diode inputs, transistor and a R/C charge
25 *                         discharge network
26 * DST_SALLEN_KEY        - Sallen-Key filter circuit
27 *
28 ************************************************************************/
29
30
31/************************************************************************
32 *
33 * DST_CRFILTER - Usage of node_description values for CR filter
34 *
35 * input[0]    - Enable input value
36 * input[1]    - input value
37 * input[2]    - Resistor value (initialization only)
38 * input[3]    - Capacitor Value (initialization only)
39 * input[4]    - Voltage reference. Usually 0V.
40 *
41 ************************************************************************/
42#define DST_CRFILTER__IN        DISCRETE_INPUT(0)
43#define DST_CRFILTER__R         DISCRETE_INPUT(1)
44#define DST_CRFILTER__C         DISCRETE_INPUT(2)
45#define DST_CRFILTER__VREF      DISCRETE_INPUT(3)
46
47DISCRETE_STEP(dst_crfilter)
48{
49   if (UNEXPECTED(m_has_rc_nodes))
50   {
51      double rc = DST_CRFILTER__R * DST_CRFILTER__C;
52      if (rc != m_rc)
53      {
54         m_rc = rc;
55         m_exponent = RC_CHARGE_EXP(rc);
56      }
57   }
58
59   double v_out = DST_CRFILTER__IN - m_vCap;
60   double v_diff = v_out - DST_CRFILTER__VREF;
61   set_output(0,  v_out);
62   m_vCap += v_diff * m_exponent;
63}
64
65DISCRETE_RESET(dst_crfilter)
66{
67   m_has_rc_nodes = this->input_is_node() & 0x6;
68   m_rc = DST_CRFILTER__R * DST_CRFILTER__C;
69   m_exponent = RC_CHARGE_EXP(m_rc);
70   m_vCap = 0;
71   set_output(0,  DST_CRFILTER__IN);
72}
73
74
75/************************************************************************
76 *
77 * DST_FILTER1 - Generic 1st order filter
78 *
79 * input[0]    - Enable input value
80 * input[1]    - input value
81 * input[2]    - Frequency value (initialization only)
82 * input[3]    - Filter type (initialization only)
83 *
84 ************************************************************************/
85#define DST_FILTER1__ENABLE DISCRETE_INPUT(0)
86#define DST_FILTER1__IN     DISCRETE_INPUT(1)
87#define DST_FILTER1__FREQ   DISCRETE_INPUT(2)
88#define DST_FILTER1__TYPE   DISCRETE_INPUT(3)
89
90static void calculate_filter1_coefficients(discrete_base_node *node, double fc, double type,
91                                 struct discrete_filter_coeff &coeff)
92{
93   double den, w, two_over_T;
94
95   /* calculate digital filter coefficents */
96   /*w = 2.0*M_PI*fc; no pre-warping */
97   w = node->sample_rate()*2.0*tan(M_PI*fc/node->sample_rate()); /* pre-warping */
98   two_over_T = 2.0*node->sample_rate();
99
100   den = w + two_over_T;
101   coeff.a1 = (w - two_over_T)/den;
102   if (type == DISC_FILTER_LOWPASS)
103   {
104      coeff.b0 = coeff.b1 = w/den;
105   }
106   else if (type == DISC_FILTER_HIGHPASS)
107   {
108      coeff.b0 = two_over_T/den;
109      coeff.b1 = -(coeff.b0);
110   }
111   else
112   {
113      /* FIXME: reenable */
114      //node->m_device->discrete_log("calculate_filter1_coefficients() - Invalid filter type for 1st order filter.");
115   }
116}
117
118DISCRETE_STEP(dst_filter1)
119{
120   double gain = 1.0;
121   double v_out;
122
123   if (DST_FILTER1__ENABLE == 0.0)
124   {
125      gain = 0.0;
126   }
127
128   v_out = -m_fc.a1*m_fc.y1 + m_fc.b0*gain*DST_FILTER1__IN + m_fc.b1*m_fc.x1;
129
130   m_fc.x1 = gain*DST_FILTER1__IN;
131   m_fc.y1 = v_out;
132   set_output(0, v_out);
133}
134
135DISCRETE_RESET(dst_filter1)
136{
137   calculate_filter1_coefficients(this, DST_FILTER1__FREQ, DST_FILTER1__TYPE, m_fc);
138   set_output(0,  0);
139}
140
141
142/************************************************************************
143 *
144 * DST_FILTER2 - Generic 2nd order filter
145 *
146 * input[0]    - Enable input value
147 * input[1]    - input value
148 * input[2]    - Frequency value (initialization only)
149 * input[3]    - Damping value (initialization only)
150 * input[4]    - Filter type (initialization only)
151 *
152 ************************************************************************/
153#define DST_FILTER2__ENABLE DISCRETE_INPUT(0)
154#define DST_FILTER2__IN     DISCRETE_INPUT(1)
155#define DST_FILTER2__FREQ   DISCRETE_INPUT(2)
156#define DST_FILTER2__DAMP   DISCRETE_INPUT(3)
157#define DST_FILTER2__TYPE   DISCRETE_INPUT(4)
158
159static void calculate_filter2_coefficients(discrete_base_node *node,
160                                 double fc, double d, double type,
161                                 struct discrete_filter_coeff &coeff)
162{
163   double w;   /* cutoff freq, in radians/sec */
164   double w_squared;
165   double den; /* temp variable */
166   double two_over_T = 2 * node->sample_rate();
167   double two_over_T_squared = two_over_T * two_over_T;
168
169   /* calculate digital filter coefficents */
170   /*w = 2.0*M_PI*fc; no pre-warping */
171   w = node->sample_rate() * 2.0 * tan(M_PI * fc / node->sample_rate()); /* pre-warping */
172   w_squared = w * w;
173
174   den = two_over_T_squared + d*w*two_over_T + w_squared;
175
176   coeff.a1 = 2.0 * (-two_over_T_squared + w_squared) / den;
177   coeff.a2 = (two_over_T_squared - d * w * two_over_T + w_squared) / den;
178
179   if (type == DISC_FILTER_LOWPASS)
180   {
181      coeff.b0 = coeff.b2 = w_squared/den;
182      coeff.b1 = 2.0 * (coeff.b0);
183   }
184   else if (type == DISC_FILTER_BANDPASS)
185   {
186      coeff.b0 = d * w * two_over_T / den;
187      coeff.b1 = 0.0;
188      coeff.b2 = -(coeff.b0);
189   }
190   else if (type == DISC_FILTER_HIGHPASS)
191   {
192      coeff.b0 = coeff.b2 = two_over_T_squared / den;
193      coeff.b1 = -2.0 * (coeff.b0);
194   }
195   else
196   {
197      /* FIXME: reenable */
198      //node->device->discrete_log("calculate_filter2_coefficients() - Invalid filter type for 2nd order filter.");
199   }
200}
201
202DISCRETE_STEP(dst_filter2)
203{
204   double gain = 1.0;
205   double v_out;
206
207   if (DST_FILTER2__ENABLE == 0.0)
208   {
209      gain = 0.0;
210   }
211
212   v_out = -m_fc.a1 * m_fc.y1 - m_fc.a2 * m_fc.y2 +
213               m_fc.b0 * gain * DST_FILTER2__IN + m_fc.b1 * m_fc.x1 + m_fc.b2 * m_fc.x2;
214
215   m_fc.x2 = m_fc.x1;
216   m_fc.x1 = gain * DST_FILTER2__IN;
217   m_fc.y2 = m_fc.y1;
218   m_fc.y1 = v_out;
219   set_output(0, v_out);
220}
221
222DISCRETE_RESET(dst_filter2)
223{
224   calculate_filter2_coefficients(this, DST_FILTER2__FREQ, DST_FILTER2__DAMP, DST_FILTER2__TYPE,
225                           m_fc);
226   set_output(0,  0);
227}
228
229
230/************************************************************************
231 *
232 * DST_OP_AMP_FILT - Op Amp filter circuit RC filter
233 *
234 * input[0]    - Enable input value
235 * input[1]    - IN0 node
236 * input[2]    - IN1 node
237 * input[3]    - Filter Type
238 *
239 * also passed discrete_op_amp_filt_info structure
240 *
241 * Mar 2004, D Renaud.
242 ************************************************************************/
243#define DST_OP_AMP_FILT__ENABLE DISCRETE_INPUT(0)
244#define DST_OP_AMP_FILT__INP1   DISCRETE_INPUT(1)
245#define DST_OP_AMP_FILT__INP2   DISCRETE_INPUT(2)
246#define DST_OP_AMP_FILT__TYPE   DISCRETE_INPUT(3)
247
248DISCRETE_STEP(dst_op_amp_filt)
249{
250   DISCRETE_DECLARE_INFO(discrete_op_amp_filt_info)
251   double v_out = 0;
252
253   double i, v = 0;
254
255   if (DST_OP_AMP_FILT__ENABLE)
256   {
257      if (m_is_norton)
258      {
259         v = DST_OP_AMP_FILT__INP1 - OP_AMP_NORTON_VBE;
260         if (v < 0) v = 0;
261      }
262      else
263      {
264         /* Millman the input voltages. */
265         i  = m_iFixed;
266         switch (m_type)
267         {
268            case DISC_OP_AMP_FILTER_IS_LOW_PASS_1_A:
269               i += (DST_OP_AMP_FILT__INP1 - DST_OP_AMP_FILT__INP2) / info->r1;
270               if (info->r2 != 0)
271                  i += (m_vP - DST_OP_AMP_FILT__INP2) / info->r2;
272               if (info->r3 != 0)
273                  i += (m_vN - DST_OP_AMP_FILT__INP2) / info->r3;
274               break;
275            default:
276               i += (DST_OP_AMP_FILT__INP1 - m_vRef) / info->r1;
277               if (info->r2 != 0)
278                  i += (DST_OP_AMP_FILT__INP2 - m_vRef) / info->r2;
279               break;
280         }
281         v = i * m_rTotal;
282      }
283
284      switch (m_type)
285      {
286         case DISC_OP_AMP_FILTER_IS_LOW_PASS_1:
287            m_vC1 += (v - m_vC1) * m_exponentC1;
288            v_out = m_vC1 * m_gain + info->vRef;
289            break;
290
291         case DISC_OP_AMP_FILTER_IS_LOW_PASS_1_A:
292            m_vC1 += (v - m_vC1) * m_exponentC1;
293            v_out = m_vC1 * m_gain + DST_OP_AMP_FILT__INP2;
294            break;
295
296         case DISC_OP_AMP_FILTER_IS_HIGH_PASS_1:
297            v_out = (v - m_vC1) * m_gain + info->vRef;
298            m_vC1 += (v - m_vC1) * m_exponentC1;
299            break;
300
301         case DISC_OP_AMP_FILTER_IS_BAND_PASS_1:
302            v_out = (v - m_vC2);
303            m_vC2 += (v - m_vC2) * m_exponentC2;
304            m_vC1 += (v_out - m_vC1) * m_exponentC1;
305            v_out = m_vC1 * m_gain + info->vRef;
306            break;
307
308         case DISC_OP_AMP_FILTER_IS_BAND_PASS_0 | DISC_OP_AMP_IS_NORTON:
309            m_vC1 += (v - m_vC1) * m_exponentC1;
310            m_vC2 += (m_vC1 - m_vC2) * m_exponentC2;
311            v = m_vC2;
312            v_out = v - m_vC3;
313            m_vC3 += (v - m_vC3) * m_exponentC3;
314            i = v_out / m_rTotal;
315            v_out = (m_iFixed - i) * info->rF;
316            break;
317
318         case DISC_OP_AMP_FILTER_IS_HIGH_PASS_0 | DISC_OP_AMP_IS_NORTON:
319            v_out = v - m_vC1;
320            m_vC1 += (v - m_vC1) * m_exponentC1;
321            i = v_out / m_rTotal;
322            v_out = (m_iFixed - i) * info->rF;
323            break;
324
325         case DISC_OP_AMP_FILTER_IS_BAND_PASS_1M:
326         case DISC_OP_AMP_FILTER_IS_BAND_PASS_1M | DISC_OP_AMP_IS_NORTON:
327            v_out = -m_fc.a1 * m_fc.y1 - m_fc.a2 * m_fc.y2 +
328                        m_fc.b0 * v + m_fc.b1 * m_fc.x1 + m_fc.b2 * m_fc.x2 +
329                        m_vRef;
330            m_fc.x2 = m_fc.x1;
331            m_fc.x1 = v;
332            m_fc.y2 = m_fc.y1;
333            break;
334      }
335
336      /* Clip the output to the voltage rails.
337       * This way we get the original distortion in all it's glory.
338       */
339      if (v_out > m_vP) v_out = m_vP;
340      if (v_out < m_vN) v_out = m_vN;
341      m_fc.y1 = v_out - m_vRef;
342      set_output(0, v_out);
343   }
344   else
345      set_output(0, 0);
346
347}
348
349DISCRETE_RESET(dst_op_amp_filt)
350{
351   DISCRETE_DECLARE_INFO(discrete_op_amp_filt_info)
352
353   /* Convert the passed filter type into an int for easy use. */
354   m_type = (int)DST_OP_AMP_FILT__TYPE & DISC_OP_AMP_FILTER_TYPE_MASK;
355   m_is_norton = (int)DST_OP_AMP_FILT__TYPE & DISC_OP_AMP_IS_NORTON;
356
357   if (m_is_norton)
358   {
359      m_vRef = 0;
360      m_rTotal = info->r1;
361      if (m_type == (DISC_OP_AMP_FILTER_IS_BAND_PASS_0 | DISC_OP_AMP_IS_NORTON))
362         m_rTotal += info->r2 +  info->r3;
363
364      /* Setup the current to the + input. */
365      m_iFixed = (info->vP - OP_AMP_NORTON_VBE) / info->r4;
366
367      /* Set the output max. */
368      m_vP =  info->vP - OP_AMP_NORTON_VBE;
369      m_vN =  info->vN;
370   }
371   else
372   {
373      m_vRef = info->vRef;
374      /* Set the output max. */
375      m_vP =  info->vP - OP_AMP_VP_RAIL_OFFSET;
376      m_vN =  info->vN;
377
378      /* Work out the input resistance.  It is all input and bias resistors in parallel. */
379      m_rTotal  = 1.0 / info->r1;         /* There has to be an R1.  Otherwise the table is wrong. */
380      if (info->r2 != 0) m_rTotal += 1.0 / info->r2;
381      if (info->r3 != 0) m_rTotal += 1.0 / info->r3;
382      m_rTotal = 1.0 / m_rTotal;
383
384      m_iFixed = 0;
385
386      m_rRatio = info->rF / (m_rTotal + info->rF);
387      m_gain = -info->rF / m_rTotal;
388   }
389
390   switch (m_type)
391   {
392      case DISC_OP_AMP_FILTER_IS_LOW_PASS_1:
393      case DISC_OP_AMP_FILTER_IS_LOW_PASS_1_A:
394         m_exponentC1 = RC_CHARGE_EXP(info->rF * info->c1);
395         m_exponentC2 =  0;
396         break;
397      case DISC_OP_AMP_FILTER_IS_HIGH_PASS_1:
398         m_exponentC1 = RC_CHARGE_EXP(m_rTotal * info->c1);
399         m_exponentC2 =  0;
400         break;
401      case DISC_OP_AMP_FILTER_IS_BAND_PASS_1:
402         m_exponentC1 = RC_CHARGE_EXP(info->rF * info->c1);
403         m_exponentC2 = RC_CHARGE_EXP(m_rTotal * info->c2);
404         break;
405      case DISC_OP_AMP_FILTER_IS_BAND_PASS_1M | DISC_OP_AMP_IS_NORTON:
406         if (info->r2 == 0)
407            m_rTotal = info->r1;
408         else
409            m_rTotal = RES_2_PARALLEL(info->r1, info->r2);
410      case DISC_OP_AMP_FILTER_IS_BAND_PASS_1M:
411      {
412         double fc = 1.0 / (2 * M_PI * sqrt(m_rTotal * info->rF * info->c1 * info->c2));
413         double d  = (info->c1 + info->c2) / sqrt(info->rF / m_rTotal * info->c1 * info->c2);
414         double gain = -info->rF / m_rTotal * info->c2 / (info->c1 + info->c2);
415
416         calculate_filter2_coefficients(this, fc, d, DISC_FILTER_BANDPASS, m_fc);
417         m_fc.b0 *= gain;
418         m_fc.b1 *= gain;
419         m_fc.b2 *= gain;
420
421         if (m_is_norton)
422            m_vRef = (info->vP - OP_AMP_NORTON_VBE) / info->r3 * info->rF;
423         else
424            m_vRef = info->vRef;
425
426         break;
427      }
428      case DISC_OP_AMP_FILTER_IS_BAND_PASS_0 | DISC_OP_AMP_IS_NORTON:
429         m_exponentC1 = RC_CHARGE_EXP(RES_2_PARALLEL(info->r1, info->r2 + info->r3 + info->r4) * info->c1);
430         m_exponentC2 = RC_CHARGE_EXP(RES_2_PARALLEL(info->r1 + info->r2, info->r3 + info->r4) * info->c2);
431         m_exponentC3 = RC_CHARGE_EXP((info->r1 + info->r2 + info->r3 + info->r4) * info->c3);
432         break;
433      case DISC_OP_AMP_FILTER_IS_HIGH_PASS_0 | DISC_OP_AMP_IS_NORTON:
434         m_exponentC1 = RC_CHARGE_EXP(info->r1 * info->c1);
435         break;
436   }
437
438   /* At startup there is no charge on the caps and output is 0V in relation to vRef. */
439   m_vC1 = 0;
440   m_vC1b = 0;
441   m_vC2 = 0;
442   m_vC3 = 0;
443
444   set_output(0,  info->vRef);
445}
446
447
448/************************************************************************
449 *
450 * DST_RC_CIRCUIT_1 - RC charge/discharge circuit
451 *
452 ************************************************************************/
453#define DST_RC_CIRCUIT_1__IN0       DISCRETE_INPUT(0)
454#define DST_RC_CIRCUIT_1__IN1       DISCRETE_INPUT(1)
455#define DST_RC_CIRCUIT_1__R         DISCRETE_INPUT(2)
456#define DST_RC_CIRCUIT_1__C         DISCRETE_INPUT(3)
457
458#define CD4066_R_ON 270
459
460DISCRETE_STEP( dst_rc_circuit_1 )
461{
462   if (DST_RC_CIRCUIT_1__IN0 == 0)
463      if (DST_RC_CIRCUIT_1__IN1 == 0)
464         /* cap is floating and does not change charge */
465         /* output is pulled to ground */
466         set_output(0,  0);
467      else
468      {
469         /* cap is discharged */
470         m_v_cap -= m_v_cap * m_exp_2;
471         set_output(0,  m_v_cap * m_v_drop);
472      }
473   else
474      if (DST_RC_CIRCUIT_1__IN1 == 0)
475      {
476         /* cap is charged */
477         m_v_cap += (5.0 - m_v_cap) * m_exp_1;
478         /* output is pulled to ground */
479         set_output(0,  0);
480      }
481      else
482      {
483         /* cap is charged slightly less */
484         m_v_cap += (m_v_charge_1_2 - m_v_cap) * m_exp_1_2;
485         set_output(0,  m_v_cap * m_v_drop);
486      }
487}
488
489DISCRETE_RESET( dst_rc_circuit_1 )
490{
491   /* the charging voltage across the cap based on in2*/
492   m_v_drop =  RES_VOLTAGE_DIVIDER(CD4066_R_ON, CD4066_R_ON + DST_RC_CIRCUIT_1__R);
493   m_v_charge_1_2 = 5.0 * m_v_drop;
494   m_v_cap = 0;
495
496   /* precalculate charging exponents */
497   /* discharge cap - in1 = 0, in2 = 1*/
498   m_exp_2 = RC_CHARGE_EXP((CD4066_R_ON + DST_RC_CIRCUIT_1__R) * DST_RC_CIRCUIT_1__C);
499   /* charge cap - in1 = 1, in2 = 0 */
500   m_exp_1 = RC_CHARGE_EXP(CD4066_R_ON * DST_RC_CIRCUIT_1__C);
501   /* charge cap - in1 = 1, in2 = 1 */
502   m_exp_1_2 = RC_CHARGE_EXP(RES_2_PARALLEL(CD4066_R_ON, CD4066_R_ON + DST_RC_CIRCUIT_1__R) * DST_RC_CIRCUIT_1__C);
503
504   /* starts at 0 until cap starts charging */
505   set_output(0,  0);
506}
507
508/************************************************************************
509 *
510 * DST_RCDISC -   Usage of node_description values for RC discharge
511 *                (inverse slope of DST_RCFILTER)
512 *
513 * input[0]    - Enable input value
514 * input[1]    - input value
515 * input[2]    - Resistor value (initialization only)
516 * input[3]    - Capacitor Value (initialization only)
517 *
518 ************************************************************************/
519#define DST_RCDISC__ENABLE  DISCRETE_INPUT(0)
520#define DST_RCDISC__IN      DISCRETE_INPUT(1)
521#define DST_RCDISC__R       DISCRETE_INPUT(2)
522#define DST_RCDISC__C       DISCRETE_INPUT(3)
523
524DISCRETE_STEP(dst_rcdisc)
525{
526   switch (m_state)
527   {
528      case 0:     /* waiting for trigger  */
529         if(DST_RCDISC__ENABLE)
530         {
531            m_state = 1;
532            m_t = 0;
533         }
534         set_output(0,  0);
535         break;
536
537      case 1:
538         if (DST_RCDISC__ENABLE)
539         {
540            set_output(0,  DST_RCDISC__IN * exp(m_t / m_exponent0));
541            m_t += this->sample_time();
542         } else
543         {
544            m_state = 0;
545         }
546   }
547}
548
549DISCRETE_RESET(dst_rcdisc)
550{
551   set_output(0,  0);
552
553   m_state = 0;
554   m_t = 0;
555   m_exponent0=-1.0 * DST_RCDISC__R * DST_RCDISC__C;
556}
557
558
559/************************************************************************
560 *
561 * DST_RCDISC2 -  Usage of node_description values for RC discharge
562 *                Has switchable charge resistor/input
563 *
564 * input[0]    - Switch input value
565 * input[1]    - input[0] value
566 * input[2]    - Resistor0 value (initialization only)
567 * input[3]    - input[1] value
568 * input[4]    - Resistor1 value (initialization only)
569 * input[5]    - Capacitor Value (initialization only)
570 *
571 ************************************************************************/
572#define DST_RCDISC2__ENABLE DISCRETE_INPUT(0)
573#define DST_RCDISC2__IN0    DISCRETE_INPUT(1)
574#define DST_RCDISC2__R0     DISCRETE_INPUT(2)
575#define DST_RCDISC2__IN1    DISCRETE_INPUT(3)
576#define DST_RCDISC2__R1     DISCRETE_INPUT(4)
577#define DST_RCDISC2__C      DISCRETE_INPUT(5)
578
579DISCRETE_STEP(dst_rcdisc2)
580{
581   double diff;
582
583   /* Works differently to other as we are always on, no enable */
584   /* exponential based in difference between input/output   */
585
586   diff = ((DST_RCDISC2__ENABLE == 0) ? DST_RCDISC2__IN0 : DST_RCDISC2__IN1) - m_v_out;
587   diff = diff - (diff * ((DST_RCDISC2__ENABLE == 0) ? m_exponent0 : m_exponent1));
588   m_v_out += diff;
589   set_output(0, m_v_out);
590}
591
592DISCRETE_RESET(dst_rcdisc2)
593{
594   m_v_out = 0;
595
596   m_state = 0;
597   m_t = 0;
598   m_exponent0 = RC_DISCHARGE_EXP(DST_RCDISC2__R0 * DST_RCDISC2__C);
599   m_exponent1 = RC_DISCHARGE_EXP(DST_RCDISC2__R1 * DST_RCDISC2__C);
600}
601
602/************************************************************************
603 *
604 * DST_RCDISC3 -  Usage of node_description values for RC discharge
605 *
606 *
607 * input[0]    - Enable
608 * input[1]    - input  value
609 * input[2]    - Resistor0 value (initialization only)
610 * input[4]    - Resistor1 value (initialization only)
611 * input[5]    - Capacitor Value (initialization only)
612 * input[6]    - Diode Junction voltage (initialization only)
613 *
614 ************************************************************************/
615#define DST_RCDISC3__ENABLE DISCRETE_INPUT(0)
616#define DST_RCDISC3__IN     DISCRETE_INPUT(1)
617#define DST_RCDISC3__R1     DISCRETE_INPUT(2)
618#define DST_RCDISC3__R2     DISCRETE_INPUT(3)
619#define DST_RCDISC3__C      DISCRETE_INPUT(4)
620#define DST_RCDISC3__DJV    DISCRETE_INPUT(5)
621
622DISCRETE_STEP(dst_rcdisc3)
623{
624   double diff;
625
626   /* Exponential based in difference between input/output   */
627
628   if(DST_RCDISC3__ENABLE)
629   {
630      diff = DST_RCDISC3__IN - m_v_out;
631      if (m_v_diode > 0)
632      {
633         if (diff > 0)
634         {
635            diff = diff * m_exponent0;
636         }
637         else if (diff < -m_v_diode)
638         {
639            diff = diff * m_exponent1;
640         }
641         else
642         {
643            diff = diff * m_exponent0;
644         }
645      }
646      else
647      {
648         if (diff < 0)
649         {
650            diff = diff * m_exponent0;
651         }
652         else if (diff > -m_v_diode)
653         {
654            diff = diff * m_exponent1;
655         }
656         else
657         {
658            diff = diff * m_exponent0;
659         }
660      }
661      m_v_out += diff;
662      set_output(0, m_v_out);
663   }
664   else
665   {
666      set_output(0, 0);
667   }
668}
669
670DISCRETE_RESET(dst_rcdisc3)
671{
672   m_v_out = 0;
673
674   m_state = 0;
675   m_t = 0;
676   m_v_diode = DST_RCDISC3__DJV;
677   m_exponent0 = RC_CHARGE_EXP(DST_RCDISC3__R1 * DST_RCDISC3__C);
678   m_exponent1 = RC_CHARGE_EXP(RES_2_PARALLEL(DST_RCDISC3__R1, DST_RCDISC3__R2) * DST_RCDISC3__C);
679}
680
681
682/************************************************************************
683 *
684 * DST_RCDISC4 -  Various charge/discharge circuits
685 *
686 * input[0]    - Enable input value
687 * input[1]    - input value
688 * input[2]    - R1 Resistor value (initialization only)
689 * input[2]    - R2 Resistor value (initialization only)
690 * input[4]    - C1 Capacitor Value (initialization only)
691 * input[4]    - vP power source (initialization only)
692 * input[4]    - circuit type (initialization only)
693 *
694 ************************************************************************/
695#define DST_RCDISC4__ENABLE DISCRETE_INPUT(0)
696#define DST_RCDISC4__IN     DISCRETE_INPUT(1)
697#define DST_RCDISC4__R1     DISCRETE_INPUT(2)
698#define DST_RCDISC4__R2     DISCRETE_INPUT(3)
699#define DST_RCDISC4__R3     DISCRETE_INPUT(4)
700#define DST_RCDISC4__C1     DISCRETE_INPUT(5)
701#define DST_RCDISC4__VP     DISCRETE_INPUT(6)
702#define DST_RCDISC4__TYPE   DISCRETE_INPUT(7)
703
704DISCRETE_STEP(dst_rcdisc4)
705{
706   int inp1 = (DST_RCDISC4__IN == 0) ? 0 : 1;
707   double v_out = 0;
708
709   if (DST_RCDISC4__ENABLE == 0)
710   {
711      set_output(0, 0);
712      return;
713   }
714
715   switch (m_type)
716   {
717      case 1:
718      case 3:
719         m_vC1 += ((m_v[inp1] - m_vC1) * m_exp[inp1]);
720         v_out = m_vC1;
721         break;
722   }
723
724   /* clip output */
725   if (v_out > m_max_out) v_out = m_max_out;
726   if (v_out < 0) v_out = 0;
727   set_output(0, v_out);
728}
729
730DISCRETE_RESET( dst_rcdisc4)
731{
732   double  v, i, r, rT;
733
734   m_type = 0;
735   /* some error checking. */
736   if (DST_RCDISC4__R1 <= 0 || DST_RCDISC4__R2 <= 0 || DST_RCDISC4__C1 <= 0 || (DST_RCDISC4__R3 <= 0 &&  m_type == 1))
737   {
738      m_device->discrete_log("Invalid component values in NODE_%d.\n", this->index());
739      return;
740   }
741   if (DST_RCDISC4__VP < 3)
742   {
743      m_device->discrete_log("vP must be >= 3V in NODE_%d.\n", this->index());
744      return;
745   }
746   if (DST_RCDISC4__TYPE < 1 || DST_RCDISC4__TYPE > 3)
747   {
748      m_device->discrete_log("Invalid circuit type in NODE_%d.\n", this->index());
749      return;
750   }
751
752   m_vC1 = 0;
753   /* store type as integer */
754   m_type = (int)DST_RCDISC4__TYPE;
755   /* setup the maximum op-amp output. */
756   m_max_out = DST_RCDISC4__VP - OP_AMP_VP_RAIL_OFFSET;
757
758   switch (m_type)
759   {
760      case 1:
761         /* We will simulate this as a voltage divider with 2 states depending
762          * on the input.  But we have to take the diodes into account.
763          */
764         v = DST_RCDISC4__VP - .5;   /* diode drop */
765
766         /* When the input is 1, both R1 & R3 are basically in parallel. */
767         r  = RES_2_PARALLEL(DST_RCDISC4__R1, DST_RCDISC4__R3);
768         rT = DST_RCDISC4__R2 + r;
769         i  = v / rT;
770         m_v[1] = i * r + .5;
771         rT = RES_2_PARALLEL(DST_RCDISC4__R2, r);
772         m_exp[1] = RC_CHARGE_EXP(rT * DST_RCDISC4__C1);
773
774         /* When the input is 0, R1 is out of circuit. */
775         rT = DST_RCDISC4__R2 + DST_RCDISC4__R3;
776         i  = v / rT;
777         m_v[0] = i * DST_RCDISC4__R3 + .5;
778         rT = RES_2_PARALLEL(DST_RCDISC4__R2, DST_RCDISC4__R3);
779         m_exp[0] = RC_CHARGE_EXP(rT * DST_RCDISC4__C1);
780         break;
781
782      case 3:
783         /* We will simulate this as a voltage divider with 2 states depending
784          * on the input.  The 1k pullup is in parallel with the internal TTL
785          * resistance, so we will just use .5k in series with R1.
786          */
787         r = 500.0 + DST_RCDISC4__R1;
788         m_v[1] = RES_VOLTAGE_DIVIDER(r, DST_RCDISC4__R2) * (5.0 - 0.5);
789         rT = RES_2_PARALLEL(r, DST_RCDISC4__R2);
790         m_exp[1] = RC_CHARGE_EXP(rT * DST_RCDISC4__C1);
791
792         /* When the input is 0, R1 is out of circuit. */
793         m_v[0] = 0;
794         m_exp[0] = RC_CHARGE_EXP(DST_RCDISC4__R2 * DST_RCDISC4__C1);
795         break;
796   }
797}
798
799/************************************************************************
800 *
801 * DST_RCDISC5 -  Diode in series with R//C
802 *
803 * input[0]    - Enable input value
804 * input[1]    - input value
805 * input[2]    - Resistor value (initialization only)
806 * input[3]    - Capacitor Value (initialization only)
807 *
808 ************************************************************************/
809#define DST_RCDISC5__ENABLE DISCRETE_INPUT(0)
810#define DST_RCDISC5__IN     DISCRETE_INPUT(1)
811#define DST_RCDISC5__R      DISCRETE_INPUT(2)
812#define DST_RCDISC5__C      DISCRETE_INPUT(3)
813
814DISCRETE_STEP( dst_rcdisc5)
815{
816   double diff,u;
817
818   /* Exponential based in difference between input/output   */
819
820   u = DST_RCDISC5__IN - 0.7; /* Diode drop */
821   if( u < 0)
822      u = 0;
823
824   diff = u - m_v_cap;
825
826   if(DST_RCDISC5__ENABLE)
827   {
828      if(diff < 0)
829         diff = diff * m_exponent0;
830
831      m_v_cap += diff;
832      set_output(0,  m_v_cap);
833   }
834   else
835   {
836      if(diff > 0)
837         m_v_cap = u;
838
839      set_output(0,  0);
840   }
841}
842
843DISCRETE_RESET( dst_rcdisc5)
844{
845   set_output(0,  0);
846
847   m_state = 0;
848   m_t = 0;
849   m_v_cap = 0;
850   m_exponent0 = RC_CHARGE_EXP(DST_RCDISC5__R * DST_RCDISC5__C);
851}
852
853
854/************************************************************************
855 *
856 * DST_RCDISC_MOD -  RC triggered by logic and modulated
857 *
858 * input[0]    - Enable input value
859 * input[1]    - input value 1
860 * input[2]    - input value 2
861 * input[3]    - Resistor 1 value (initialization only)
862 * input[4]    - Resistor 2 value (initialization only)
863 * input[5]    - Resistor 3 value (initialization only)
864 * input[6]    - Resistor 4 value (initialization only)
865 * input[7]    - Capacitor Value (initialization only)
866 * input[8]    - Voltage Value (initialization only)
867 *
868 ************************************************************************/
869#define DST_RCDISC_MOD__IN1     DISCRETE_INPUT(0)
870#define DST_RCDISC_MOD__IN2     DISCRETE_INPUT(1)
871#define DST_RCDISC_MOD__R1      DISCRETE_INPUT(2)
872#define DST_RCDISC_MOD__R2      DISCRETE_INPUT(3)
873#define DST_RCDISC_MOD__R3      DISCRETE_INPUT(4)
874#define DST_RCDISC_MOD__R4      DISCRETE_INPUT(5)
875#define DST_RCDISC_MOD__C       DISCRETE_INPUT(6)
876#define DST_RCDISC_MOD__VP      DISCRETE_INPUT(7)
877
878DISCRETE_STEP(dst_rcdisc_mod)
879{
880   double  diff, v_cap, u, vD;
881   int     mod_state, mod1_state, mod2_state;
882
883   /* Exponential based in difference between input/output   */
884   v_cap = m_v_cap;
885
886   mod1_state = DST_RCDISC_MOD__IN1 > 0.5;
887   mod2_state = DST_RCDISC_MOD__IN2 > 0.6;
888   mod_state  = (mod2_state << 1) + mod1_state;
889
890   u = mod1_state ? 0 : DST_RCDISC_MOD__VP;
891   /* Clamp */
892   diff = u - v_cap;
893   vD = diff * m_vd_gain[mod_state];
894   if (vD < -0.6)
895   {
896      diff  = u + 0.6 - v_cap;
897      diff -= diff * m_exp_low[mod1_state];
898      v_cap += diff;
899      set_output(0,  mod2_state ? 0 : -0.6);
900   }
901   else
902   {
903      diff  -= diff * m_exp_high[mod_state];
904      v_cap += diff;
905      /* neglecting current through R3 drawn by next8 node */
906      set_output(0,  mod2_state ? 0: (u - v_cap) * m_gain[mod1_state]);
907   }
908   m_v_cap = v_cap;
909}
910
911DISCRETE_RESET(dst_rcdisc_mod)
912{
913   double  rc[2], rc2[2];
914
915   /* pre-calculate fixed values */
916   /* DST_RCDISC_MOD__IN1 <= 0.5 */
917   rc[0] = DST_RCDISC_MOD__R1 + DST_RCDISC_MOD__R2;
918   if (rc[0] < 1) rc[0] = 1;
919   m_exp_low[0]  = RC_DISCHARGE_EXP(DST_RCDISC_MOD__C * rc[0]);
920   m_gain[0]     = RES_VOLTAGE_DIVIDER(rc[0], DST_RCDISC_MOD__R4);
921   /* DST_RCDISC_MOD__IN1 > 0.5 */
922   rc[1] = DST_RCDISC_MOD__R2;
923   if (rc[1] < 1) rc[1] = 1;
924   m_exp_low[1]  = RC_DISCHARGE_EXP(DST_RCDISC_MOD__C * rc[1]);
925   m_gain[1]     = RES_VOLTAGE_DIVIDER(rc[1], DST_RCDISC_MOD__R4);
926   /* DST_RCDISC_MOD__IN2 <= 0.6 */
927   rc2[0] = DST_RCDISC_MOD__R4;
928   /* DST_RCDISC_MOD__IN2 > 0.6 */
929   rc2[1] = RES_2_PARALLEL(DST_RCDISC_MOD__R3, DST_RCDISC_MOD__R4);
930   /* DST_RCDISC_MOD__IN1 <= 0.5 && DST_RCDISC_MOD__IN2 <= 0.6 */
931   m_exp_high[0] = RC_DISCHARGE_EXP(DST_RCDISC_MOD__C * (rc[0] + rc2[0]));
932   m_vd_gain[0]  = RES_VOLTAGE_DIVIDER(rc[0], rc2[0]);
933   /* DST_RCDISC_MOD__IN1 > 0.5  && DST_RCDISC_MOD__IN2 <= 0.6 */
934   m_exp_high[1] = RC_DISCHARGE_EXP(DST_RCDISC_MOD__C * (rc[1] + rc2[0]));
935   m_vd_gain[1]  = RES_VOLTAGE_DIVIDER(rc[1], rc2[0]);
936   /* DST_RCDISC_MOD__IN1 <= 0.5 && DST_RCDISC_MOD__IN2 > 0.6 */
937   m_exp_high[2] = RC_DISCHARGE_EXP(DST_RCDISC_MOD__C * (rc[0] + rc2[1]));
938   m_vd_gain[2]  = RES_VOLTAGE_DIVIDER(rc[0], rc2[1]);
939   /* DST_RCDISC_MOD__IN1 > 0.5  && DST_RCDISC_MOD__IN2 > 0.6 */
940   m_exp_high[3] = RC_DISCHARGE_EXP(DST_RCDISC_MOD__C * (rc[1] + rc2[1]));
941   m_vd_gain[3]  = RES_VOLTAGE_DIVIDER(rc[1], rc2[1]);
942
943   m_v_cap  = 0;
944   set_output(0,  0);
945}
946
947/************************************************************************
948 *
949 * DST_RCFILTER - Usage of node_description values for RC filter
950 *
951 * input[0]    - Enable input value
952 * input[1]    - input value
953 * input[2]    - Resistor value (initialization only)
954 * input[3]    - Capacitor Value (initialization only)
955 * input[4]    - Voltage reference. Usually 0V.
956 *
957 ************************************************************************/
958#define DST_RCFILTER__VIN       DISCRETE_INPUT(0)
959#define DST_RCFILTER__R         DISCRETE_INPUT(1)
960#define DST_RCFILTER__C         DISCRETE_INPUT(2)
961#define DST_RCFILTER__VREF      DISCRETE_INPUT(3)
962
963DISCRETE_STEP(dst_rcfilter)
964{
965   if (EXPECTED(m_is_fast))
966      m_v_out += ((DST_RCFILTER__VIN - m_v_out) * m_exponent);
967   else
968   {
969      if (UNEXPECTED(m_has_rc_nodes))
970      {
971         double rc = DST_RCFILTER__R * DST_RCFILTER__C;
972         if (rc != m_rc)
973         {
974            m_rc = rc;
975            m_exponent = RC_CHARGE_EXP(rc);
976         }
977      }
978
979      /************************************************************************/
980      /* Next Value = PREV + (INPUT_VALUE - PREV)*(1-(EXP(-TIMEDELTA/RC)))    */
981      /************************************************************************/
982
983      m_vCap += ((DST_RCFILTER__VIN - m_v_out) * m_exponent);
984      m_v_out = m_vCap + DST_RCFILTER__VREF;
985   }
986   set_output(0,  m_v_out);
987}
988
989
990DISCRETE_RESET(dst_rcfilter)
991{
992   m_has_rc_nodes = this->input_is_node() & 0x6;
993   m_rc = DST_RCFILTER__R * DST_RCFILTER__C;
994   m_exponent = RC_CHARGE_EXP(m_rc);
995   m_vCap   = 0;
996   m_v_out = 0;
997   /* FIXME --> we really need another class here */
998   if (!m_has_rc_nodes && DST_RCFILTER__VREF == 0)
999      m_is_fast = 1;
1000   else
1001      m_is_fast = 0;
1002}
1003
1004/************************************************************************
1005 *
1006 * DST_RCFILTER_SW - Usage of node_description values for switchable RC filter
1007 *
1008 * input[0]    - Enable input value
1009 * input[1]    - input value
1010 * input[2]    - Resistor value (initialization only)
1011 * input[3]    - Capacitor Value (initialization only)
1012 * input[4]    - Voltage reference. Usually 0V.
1013 *
1014 ************************************************************************/
1015#define DST_RCFILTER_SW__ENABLE     DISCRETE_INPUT(0)
1016#define DST_RCFILTER_SW__VIN        DISCRETE_INPUT(1)
1017#define DST_RCFILTER_SW__SWITCH     DISCRETE_INPUT(2)
1018#define DST_RCFILTER_SW__R          DISCRETE_INPUT(3)
1019#define DST_RCFILTER_SW__C(x)       DISCRETE_INPUT(4+x)
1020
1021/* 74HC4066 : 15
1022 * 74VHC4066 : 15
1023 * UTC4066 : 270 @ 5VCC, 80 @ 15VCC
1024 * CD4066BC : 270 (Fairchild)
1025 *
1026 * The choice below makes scramble sound about "right". For future error reports,
1027 * we need the exact type of switch and at which voltage (5, 12?) it is operated.
1028 */
1029#define CD4066_ON_RES (40)
1030
1031// FIXME: This needs optimization !
1032DISCRETE_STEP(dst_rcfilter_sw)
1033{
1034   int i;
1035   int bits = (int)DST_RCFILTER_SW__SWITCH;
1036   double us = 0;
1037   double vIn = DST_RCFILTER_SW__VIN;
1038   double v_out;
1039
1040   if (EXPECTED(DST_RCFILTER_SW__ENABLE))
1041   {
1042      switch (bits)
1043      {
1044      case 0:
1045         v_out = vIn;
1046         break;
1047      case 1:
1048         m_vCap[0] += (vIn - m_vCap[0]) * m_exp0;
1049         v_out = m_vCap[0] + (vIn - m_vCap[0]) * m_factor;
1050         break;
1051      case 2:
1052         m_vCap[1] += (vIn - m_vCap[1]) * m_exp1;
1053         v_out = m_vCap[1] + (vIn - m_vCap[1]) * m_factor;
1054         break;
1055      default:
1056         for (i = 0; i < 4; i++)
1057         {
1058            if (( bits & (1 << i)) != 0)
1059               us += m_vCap[i];
1060         }
1061         v_out = m_f1[bits] * vIn + m_f2[bits]  * us;
1062         for (i = 0; i < 4; i++)
1063         {
1064            if (( bits & (1 << i)) != 0)
1065               m_vCap[i] += (v_out - m_vCap[i]) * m_exp[i];
1066         }
1067      }
1068      set_output(0, v_out);
1069   }
1070   else
1071   {
1072      set_output(0, 0);
1073   }
1074}
1075
1076DISCRETE_RESET(dst_rcfilter_sw)
1077{
1078   int i, bits;
1079
1080   for (i = 0; i < 4; i++)
1081   {
1082      m_vCap[i] = 0;
1083      m_exp[i] = RC_CHARGE_EXP( CD4066_ON_RES * DST_RCFILTER_SW__C(i));
1084   }
1085
1086   for (bits=0; bits < 15; bits++)
1087   {
1088      double rs = 0;
1089
1090      for (i = 0; i < 4; i++)
1091      {
1092         if (( bits & (1 << i)) != 0)
1093            rs += DST_RCFILTER_SW__R;
1094      }
1095      m_f1[bits] = RES_VOLTAGE_DIVIDER(rs, CD4066_ON_RES);
1096      m_f2[bits] = DST_RCFILTER_SW__R / (CD4066_ON_RES + rs);
1097   }
1098
1099
1100   /* fast cases */
1101   m_exp0 = RC_CHARGE_EXP((CD4066_ON_RES + DST_RCFILTER_SW__R) * DST_RCFILTER_SW__C(0));
1102   m_exp1 = RC_CHARGE_EXP((CD4066_ON_RES + DST_RCFILTER_SW__R) * DST_RCFILTER_SW__C(1));
1103   m_factor = RES_VOLTAGE_DIVIDER(DST_RCFILTER_SW__R, CD4066_ON_RES);
1104
1105   set_output(0,  0);
1106}
1107
1108
1109/************************************************************************
1110 *
1111 * DST_RCINTEGRATE - Two diode inputs, transistor and a R/C charge
1112 *                   discharge network
1113 *
1114 * input[0]    - Enable input value
1115 * input[1]    - input value 1
1116 * input[2]    - input value 2
1117 * input[3]    - Resistor 1 value (initialization only)
1118 * input[4]    - Resistor 2 value (initialization only)
1119 * input[5]    - Capacitor Value (initialization only)
1120 *
1121 ************************************************************************/
1122#define DST_RCINTEGRATE__IN1    DISCRETE_INPUT(0)
1123#define DST_RCINTEGRATE__R1     DISCRETE_INPUT(1)
1124#define DST_RCINTEGRATE__R2     DISCRETE_INPUT(2)
1125#define DST_RCINTEGRATE__R3     DISCRETE_INPUT(3)
1126#define DST_RCINTEGRATE__C      DISCRETE_INPUT(4)
1127#define DST_RCINTEGRATE__VP     DISCRETE_INPUT(5)
1128#define DST_RCINTEGRATE__TYPE   DISCRETE_INPUT(6)
1129
1130/* Ebers-Moll large signal model
1131 * Couriersud:
1132 * The implementation avoids all iterative approaches in order not to burn cycles
1133 * We will calculate Ic from vBE and use this as an indication where to go.
1134 * The implementation may oscillate if you change the weighting factors at the
1135 * end.
1136 *
1137 * This implementation is not perfect, but does it's job in dkong'
1138 */
1139
1140/* reverse saturation current */
1141#define IES     7e-15
1142#define ALPHAT  0.99
1143#define KT      0.026
1144#define EM_IC(x) (ALPHAT * IES * exp( (x) / KT - 1.0 ))
1145
1146DISCRETE_STEP( dst_rcintegrate)
1147{
1148   double diff, u, iQ, iQc, iC, RG, vE;
1149   double vP;
1150
1151   u  = DST_RCINTEGRATE__IN1;
1152   vP = DST_RCINTEGRATE__VP;
1153
1154   if ( u - 0.7  < m_vCap * m_gain_r1_r2)
1155   {
1156      /* discharge .... */
1157      diff  = 0.0 - m_vCap;
1158      iC    = m_c_exp1 * diff; /* iC */
1159      diff -= diff * m_exp_exponent1;
1160      m_vCap += diff;
1161      iQ = 0;
1162      vE = m_vCap * m_gain_r1_r2;
1163      RG = vE / iC;
1164   }
1165   else
1166   {
1167      /* charging */
1168      diff  = (vP - m_vCE) * m_f - m_vCap;
1169      iC    = 0.0 - m_c_exp0 * diff; /* iC */
1170      diff -= diff * m_exp_exponent0;
1171      m_vCap += diff;
1172      iQ = iC + (iC * DST_RCINTEGRATE__R1 + m_vCap) / DST_RCINTEGRATE__R2;
1173      RG = (vP - m_vCE) / iQ;
1174      vE = (RG - DST_RCINTEGRATE__R3) / RG * (vP - m_vCE);
1175   }
1176
1177
1178   u = DST_RCINTEGRATE__IN1;
1179   if (u > 0.7 + vE)
1180   {
1181      vE = u - 0.7;
1182      //iQc = EM_IC(u - vE);
1183      iQc = m_EM_IC_0_7;
1184   }
1185   else
1186      iQc = EM_IC(u - vE);
1187
1188   m_vCE = MIN(vP - 0.1, vP - RG * iQc);
1189
1190   /* Avoid oscillations
1191    * The method tends to largely overshoot - no wonder without
1192    * iterative solution approximation
1193    */
1194
1195   m_vCE = MAX(m_vCE, 0.1 );
1196   m_vCE = 0.1 * m_vCE + 0.9 * (vP - vE - iQ * DST_RCINTEGRATE__R3);
1197
1198   switch (m_type)
1199   {
1200      case DISC_RC_INTEGRATE_TYPE1:
1201         set_output(0,  m_vCap);
1202         break;
1203      case DISC_RC_INTEGRATE_TYPE2:
1204         set_output(0,  vE);
1205         break;
1206      case DISC_RC_INTEGRATE_TYPE3:
1207         set_output(0,  MAX(0, vP - iQ * DST_RCINTEGRATE__R3));
1208         break;
1209   }
1210}
1211
1212DISCRETE_RESET(dst_rcintegrate)
1213{
1214   double r;
1215   double dt = this->sample_time();
1216
1217   m_type = DST_RCINTEGRATE__TYPE;
1218
1219   m_vCap = 0;
1220   m_vCE  = 0;
1221
1222   /* pre-calculate fixed values */
1223   m_gain_r1_r2 = RES_VOLTAGE_DIVIDER(DST_RCINTEGRATE__R1, DST_RCINTEGRATE__R2);
1224
1225   r = DST_RCINTEGRATE__R1 / DST_RCINTEGRATE__R2 * DST_RCINTEGRATE__R3 + DST_RCINTEGRATE__R1 + DST_RCINTEGRATE__R3;
1226
1227   m_f = RES_VOLTAGE_DIVIDER(DST_RCINTEGRATE__R3, DST_RCINTEGRATE__R2);
1228   m_exponent0 = -1.0 * r * m_f * DST_RCINTEGRATE__C;
1229   m_exponent1 = -1.0 * (DST_RCINTEGRATE__R1 + DST_RCINTEGRATE__R2) * DST_RCINTEGRATE__C;
1230   m_exp_exponent0 = exp(dt / m_exponent0);
1231   m_exp_exponent1 = exp(dt / m_exponent1);
1232   m_c_exp0 =  DST_RCINTEGRATE__C / m_exponent0 * m_exp_exponent0;
1233   m_c_exp1 =  DST_RCINTEGRATE__C / m_exponent1 * m_exp_exponent1;
1234
1235   m_EM_IC_0_7 = EM_IC(0.7);
1236
1237   set_output(0,  0);
1238}
1239
1240/************************************************************************
1241 *
1242 * DST_SALLEN_KEY - Sallen-Key filter circuit
1243 *
1244 * input[0]    - Enable input value
1245 * input[1]    - IN0 node
1246 * input[3]    - Filter Type
1247 *
1248 * also passed discrete_op_amp_filt_info structure
1249 *
1250 * 2008, couriersud
1251 ************************************************************************/
1252#define DST_SALLEN_KEY__ENABLE  DISCRETE_INPUT(0)
1253#define DST_SALLEN_KEY__INP0    DISCRETE_INPUT(1)
1254#define DST_SALLEN_KEY__TYPE    DISCRETE_INPUT(2)
1255
1256DISCRETE_STEP(dst_sallen_key)
1257{
1258   double gain = 1.0;
1259   double v_out;
1260
1261   if (DST_SALLEN_KEY__ENABLE == 0.0)
1262   {
1263      gain = 0.0;
1264   }
1265
1266   v_out = -m_fc.a1 * m_fc.y1 - m_fc.a2 * m_fc.y2 +
1267               m_fc.b0 * gain * DST_SALLEN_KEY__INP0 + m_fc.b1 * m_fc.x1 + m_fc.b2 * m_fc.x2;
1268
1269   m_fc.x2 = m_fc.x1;
1270   m_fc.x1 = gain * DST_SALLEN_KEY__INP0;
1271   m_fc.y2 = m_fc.y1;
1272   m_fc.y1 = v_out;
1273   set_output(0, v_out);
1274}
1275
1276DISCRETE_RESET(dst_sallen_key)
1277{
1278   DISCRETE_DECLARE_INFO(discrete_op_amp_filt_info)
1279
1280   double freq, q;
1281
1282   switch ((int) DST_SALLEN_KEY__TYPE)
1283   {
1284      case DISC_SALLEN_KEY_LOW_PASS:
1285         freq = 1.0 / ( 2.0 * M_PI * sqrt(info->c1 * info->c2 * info->r1 * info->r2));
1286         q = sqrt(info->c1 * info->c2 * info->r1 * info->r2) / (info->c2 * (info->r1 + info->r2));
1287         break;
1288      default:
1289         fatalerror("Unknown sallen key filter type\n");
1290   }
1291
1292   calculate_filter2_coefficients(this, freq, 1.0 / q, DISC_FILTER_LOWPASS, m_fc);
1293   set_output(0,  0);
1294}
1295
1296
1297/* !!!!!!!!!!! NEW FILTERS for testing !!!!!!!!!!!!!!!!!!!!! */
1298
1299
1300/************************************************************************
1301 *
1302 * DST_RCFILTERN - Usage of node_description values for RC filter
1303 *
1304 * input[0]    - Enable input value
1305 * input[1]    - input value
1306 * input[2]    - Resistor value (initialization only)
1307 * input[3]    - Capacitor Value (initialization only)
1308 *
1309 ************************************************************************/
1310#define DST_RCFILTERN__ENABLE       DISCRETE_INPUT(0)
1311#define DST_RCFILTERN__IN       DISCRETE_INPUT(1)
1312#define DST_RCFILTERN__R        DISCRETE_INPUT(2)
1313#define DST_RCFILTERN__C        DISCRETE_INPUT(3)
1314
1315#if 0
1316DISCRETE_RESET(dst_rcfilterN)
1317{
1318#if 0
1319   double f=1.0/(2*M_PI* DST_RCFILTERN__R * DST_RCFILTERN__C);
1320
1321/* !!!!!!!!!!!!!! CAN'T CHEAT LIKE THIS !!!!!!!!!!!!!!!! */
1322/* Put this stuff in a context */
1323
1324   this->m_input[2] = f;
1325   this->m_input[3] = DISC_FILTER_LOWPASS;
1326
1327   /* Use first order filter */
1328   dst_filter1_reset(node);
1329#endif
1330}
1331#endif
1332
1333/************************************************************************
1334 *
1335 * DST_RCDISCN -   Usage of node_description values for RC discharge
1336 *                (inverse slope of DST_RCFILTER)
1337 *
1338 * input[0]    - Enable input value
1339 * input[1]    - input value
1340 * input[2]    - Resistor value (initialization only)
1341 * input[3]    - Capacitor Value (initialization only)
1342 *
1343 ************************************************************************/
1344#define DST_RCDISCN__ENABLE DISCRETE_INPUT(0)
1345#define DST_RCDISCN__IN     DISCRETE_INPUT(1)
1346#define DST_RCDISCN__R      DISCRETE_INPUT(2)
1347#define DST_RCDISCN__C      DISCRETE_INPUT(3)
1348
1349DISCRETE_RESET(dst_rcdiscN)
1350{
1351#if 0
1352   double f = 1.0 / (2 * M_PI * DST_RCDISCN__R * DST_RCDISCN__C);
1353
1354/* !!!!!!!!!!!!!! CAN'T CHEAT LIKE THIS !!!!!!!!!!!!!!!! */
1355/* Put this stuff in a context */
1356
1357   this->m_input[2] = f;
1358   this->m_input[3] = DISC_FILTER_LOWPASS;
1359
1360   /* Use first order filter */
1361   dst_filter1_reset(node);
1362#endif
1363}
1364
1365DISCRETE_STEP(dst_rcdiscN)
1366{
1367   double gain = 1.0;
1368   double v_out;
1369
1370   if (DST_RCDISCN__ENABLE == 0.0)
1371   {
1372      gain = 0.0;
1373   }
1374
1375   /* A rise in the input signal results in an instant charge, */
1376   /* else discharge through the RC to zero */
1377   if (gain* DST_RCDISCN__IN > m_x1)
1378      v_out = gain* DST_RCDISCN__IN;
1379   else
1380      v_out = -m_a1*m_y1;
1381
1382   m_x1 = gain* DST_RCDISCN__IN;
1383   m_y1 = v_out;
1384   set_output(0, v_out);
1385}
1386
1387
1388/************************************************************************
1389 *
1390 * DST_RCDISC2N -  Usage of node_description values for RC discharge
1391 *                Has switchable charge resistor/input
1392 *
1393 * input[0]    - Switch input value
1394 * input[1]    - input[0] value
1395 * input[2]    - Resistor0 value (initialization only)
1396 * input[3]    - input[1] value
1397 * input[4]    - Resistor1 value (initialization only)
1398 * input[5]    - Capacitor Value (initialization only)
1399 *
1400 ************************************************************************/
1401#define DST_RCDISC2N__ENABLE    DISCRETE_INPUT(0)
1402#define DST_RCDISC2N__IN0       DISCRETE_INPUT(1)
1403#define DST_RCDISC2N__R0        DISCRETE_INPUT(2)
1404#define DST_RCDISC2N__IN1       DISCRETE_INPUT(3)
1405#define DST_RCDISC2N__R1        DISCRETE_INPUT(4)
1406#define DST_RCDISC2N__C         DISCRETE_INPUT(5)
1407
1408
1409DISCRETE_STEP(dst_rcdisc2N)
1410{
1411   double inp = ((DST_RCDISC2N__ENABLE == 0) ? DST_RCDISC2N__IN0 : DST_RCDISC2N__IN1);
1412   double v_out;
1413
1414   if (DST_RCDISC2N__ENABLE == 0)
1415      v_out = -m_fc0.a1*m_y1 + m_fc0.b0*inp + m_fc0.b1 * m_x1;
1416   else
1417      v_out = -m_fc1.a1*m_y1 + m_fc1.b0*inp + m_fc1.b1*m_x1;
1418
1419   m_x1 = inp;
1420   m_y1 = v_out;
1421   set_output(0, v_out);
1422}
1423
1424DISCRETE_RESET(dst_rcdisc2N)
1425{
1426   double f1,f2;
1427
1428   f1 = 1.0 / (2 * M_PI * DST_RCDISC2N__R0 * DST_RCDISC2N__C);
1429   f2 = 1.0 / (2 * M_PI * DST_RCDISC2N__R1 * DST_RCDISC2N__C);
1430
1431   calculate_filter1_coefficients(this, f1, DISC_FILTER_LOWPASS, m_fc0);
1432   calculate_filter1_coefficients(this, f2, DISC_FILTER_LOWPASS, m_fc1);
1433
1434   /* Initialize the object */
1435   set_output(0,  0);
1436}
Property changes on: trunk/src/emu/sound/disc_flt.inc
Added: svn:mime-type
   + text/plain
Added: svn:eol-style
   + native
trunk/src/emu/sound/disc_mth.inc
r0r28732
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 *  (c) D.Renaud 2003-2004
9 *
10 ************************************************************************
11 *
12 * DST_ADDDER            - Multichannel adder
13 * DST_BITS_DECODE       - Decode Bits from input node
14 * DST_CLAMP             - Simple signal clamping circuit
15 * DST_COMP_ADDER        - Selectable parallel component circuit
16 * DST_DAC_R1            - R1 Ladder DAC with cap filtering
17 * DST_DIODE_MIX         - Diode mixer
18 * DST_DIVIDE            - Division function
19 * DST_GAIN              - Gain Factor
20 * DST_INTEGRATE         - Integration circuits
21 * DST_LOGIC_INV         - Logic level invertor
22 * DST_LOGIC_AND         - Logic AND gate 4 input
23 * DST_LOGIC_NAND        - Logic NAND gate 4 input
24 * DST_LOGIC_OR          - Logic OR gate 4 input
25 * DST_LOGIC_NOR         - Logic NOR gate 4 input
26 * DST_LOGIC_XOR         - Logic XOR gate 2 input
27 * DST_LOGIC_NXOR        - Logic NXOR gate 2 input
28 * DST_LOGIC_DFF         - Logic D-type flip/flop
29 * DST_LOGIC_JKFF        - Logic JK-type flip/flop
30 * DST_LOGIC_SHIFT       - Logic Shift Register
31 * DST_LOOKUP_TABLE      - Return value from lookup table
32 * DST_MIXER             - Final Mixer Stage
33 * DST_MULTIPLEX         - 1 of x Multiplexer/switch
34 * DST_ONESHOT           - One shot pulse generator
35 * DST_RAMP              - Ramp up/down
36 * DST_SAMPHOLD          - Sample & Hold Implementation
37 * DST_SWITCH            - Switch implementation
38 * DST_ASWITCH           - Analog switch
39 * DST_TRANSFORM         - Multiple math functions
40 * DST_OP_AMP            - Op Amp circuits
41 * DST_OP_AMP_1SHT       - Op Amp One Shot
42 * DST_TVCA_OP_AMP       - Triggered op amp voltage controlled amplifier
43 * DST_XTIME_BUFFER      - Buffer/Invertor gate implementation using X_TIME
44 * DST_XTIME_AND         - AND/NAND gate implementation using X_TIME
45 * DST_XTIME_OR          - OR/NOR gate implementation using X_TIME
46 * DST_XTIME_XOR         - XOR/XNOR gate implementation using X_TIME
47 *
48 ************************************************************************/
49
50#include <float.h>
51
52
53
54/************************************************************************
55 *
56 * DST_ADDER - This is a 4 channel input adder with enable function
57 *
58 * input[0]    - Enable input value
59 * input[1]    - Channel0 input value
60 * input[2]    - Channel1 input value
61 * input[3]    - Channel2 input value
62 * input[4]    - Channel3 input value
63 *
64 ************************************************************************/
65#define DST_ADDER__ENABLE   DISCRETE_INPUT(0)
66#define DST_ADDER__IN0      DISCRETE_INPUT(1)
67#define DST_ADDER__IN1      DISCRETE_INPUT(2)
68#define DST_ADDER__IN2      DISCRETE_INPUT(3)
69#define DST_ADDER__IN3      DISCRETE_INPUT(4)
70
71DISCRETE_STEP(dst_adder)
72{
73   if(DST_ADDER__ENABLE)
74   {
75      set_output(0,  DST_ADDER__IN0 + DST_ADDER__IN1 + DST_ADDER__IN2 + DST_ADDER__IN3);
76   }
77   else
78   {
79      set_output(0, 0);
80   }
81}
82
83
84/************************************************************************
85 *
86 * DST_COMP_ADDER  - Selectable parallel component adder
87 *
88 * input[0]    - Bit Select
89 *
90 * Also passed discrete_comp_adder_table structure
91 *
92 * Mar 2004, D Renaud.
93 ************************************************************************/
94#define DST_COMP_ADDER__SELECT  DISCRETE_INPUT(0)
95
96DISCRETE_STEP(dst_comp_adder)
97{
98   int select;
99
100   select = (int)DST_COMP_ADDER__SELECT;
101   assert(select < 256);
102   set_output(0,  m_total[select]);
103}
104
105DISCRETE_RESET(dst_comp_adder)
106{
107   DISCRETE_DECLARE_INFO(discrete_comp_adder_table)
108
109   int i, bit;
110   int bit_length = info->length;
111
112   assert(bit_length <= 8);
113
114   /* pre-calculate all possible values to speed up step routine */
115   for(i = 0; i < 256; i++)
116   {
117      switch (info->type)
118      {
119         case DISC_COMP_P_CAPACITOR:
120            m_total[i] = info->cDefault;
121            for(bit = 0; bit < bit_length; bit++)
122            {
123               if (i & (1 << bit))
124                  m_total[i] += info->c[bit];
125            }
126            break;
127         case DISC_COMP_P_RESISTOR:
128            m_total[i] = (info->cDefault != 0) ? 1.0 / info->cDefault : 0;
129            for(bit = 0; bit < bit_length; bit++)
130            {
131               if ((i & (1 << bit)) && (info->c[bit] != 0))
132                  m_total[i] += 1.0 / info->c[bit];
133            }
134            if (m_total[i] != 0)
135               m_total[i] = 1.0 / m_total[i];
136            break;
137      }
138   }
139   set_output(0,  m_total[0]);
140}
141
142/************************************************************************
143 *
144 * DST_CLAMP - Simple signal clamping circuit
145 *
146 * input[0]    - Input value
147 * input[1]    - Minimum value
148 * input[2]    - Maximum value
149 *
150 ************************************************************************/
151#define DST_CLAMP__IN       DISCRETE_INPUT(0)
152#define DST_CLAMP__MIN      DISCRETE_INPUT(1)
153#define DST_CLAMP__MAX      DISCRETE_INPUT(2)
154
155DISCRETE_STEP(dst_clamp)
156{
157   if (DST_CLAMP__IN < DST_CLAMP__MIN)
158      set_output(0,  DST_CLAMP__MIN);
159   else if (DST_CLAMP__IN > DST_CLAMP__MAX)
160      set_output(0,  DST_CLAMP__MAX);
161   else
162      set_output(0, DST_CLAMP__IN);
163}
164
165
166/************************************************************************
167 *
168 * DST_DAC_R1 - R1 Ladder DAC with cap smoothing
169 *
170 * input[0]    - Binary Data Input
171 * input[1]    - Data On Voltage (3.4 for TTL)
172 *
173 * also passed discrete_dac_r1_ladder structure
174 *
175 * Mar 2004, D Renaud.
176 * Nov 2010, D Renaud. - optimized for speed
177 ************************************************************************/
178#define DST_DAC_R1__DATA        DISCRETE_INPUT(0)
179#define DST_DAC_R1__VON         DISCRETE_INPUT(1)
180
181DISCRETE_STEP(dst_dac_r1)
182{
183   int     data = (int)DST_DAC_R1__DATA;
184   double  v = m_v_step[data];
185   double  x_time = DST_DAC_R1__DATA - data;
186   double  last_v = m_last_v;
187
188   m_last_v = v;
189
190   if (x_time > 0)
191      v = x_time * (v - last_v) + last_v;
192
193   /* Filter if needed, else just output voltage */
194   if (m_has_c_filter)
195   {
196      double v_diff = v - m_v_out;
197      /* optimization - if charged close enough to voltage */
198      if (fabs(v_diff) < 0.000001)
199         m_v_out = v;
200      else
201      {
202         m_v_out += v_diff * m_exponent;
203      }
204   }
205   else
206      m_v_out = v;
207
208   set_output(0, m_v_out);
209}
210
211DISCRETE_RESET(dst_dac_r1)
212{
213   DISCRETE_DECLARE_INFO(discrete_dac_r1_ladder)
214
215   int bit;
216   int ladderLength = info->ladderLength;
217   int total_steps = 1 << ladderLength;
218   double r_total = 0;
219   double i_bias;
220   double v_on = DST_DAC_R1__VON;
221
222   m_last_v = 0;
223
224   /* Calculate the Millman current of the bias circuit */
225   if (info->rBias > 0)
226      i_bias = info->vBias / info->rBias;
227   else
228      i_bias = 0;
229
230   /*
231    * We will do a small amount of error checking.
232    * But if you are an idiot and pass a bad ladder table
233    * then you deserve a crash.
234    */
235   if (ladderLength < 2 && info->rBias == 0 && info->rGnd == 0)
236   {
237      /* You need at least 2 resistors for a ladder */
238      m_device->discrete_log("dst_dac_r1_reset - Ladder length too small");
239   }
240   if (ladderLength > DISC_LADDER_MAXRES )
241   {
242      m_device->discrete_log("dst_dac_r1_reset - Ladder length exceeds DISC_LADDER_MAXRES");
243   }
244
245   /*
246    * Calculate the total of all resistors in parallel.
247    * This is the combined resistance of the voltage sources.
248    * This is used for the charging curve.
249    */
250   for(bit = 0; bit < ladderLength; bit++)
251   {
252      if (info->r[bit] > 0)
253         r_total += 1.0 / info->r[bit];
254   }
255   if (info->rBias > 0) r_total += 1.0 / info->rBias;
256   if (info->rGnd > 0)  r_total += 1.0 / info->rGnd;
257   r_total = 1.0 / r_total;
258
259   m_v_out = 0;
260
261   if (info->cFilter > 0)
262   {
263      m_has_c_filter = 1;
264      /* Setup filter constant */
265      m_exponent = RC_CHARGE_EXP(r_total * info->cFilter);
266   }
267   else
268      m_has_c_filter = 0;
269
270   /* pre-calculate all possible values to speed up step routine */
271   for(int i = 0; i < total_steps; i++)
272   {
273      double i_total = i_bias;
274      for (bit = 0; bit < ladderLength; bit++)
275      {
276         /* Add up currents of ON circuits per Millman. */
277
278         /* ignore if no resistor present */
279         if (EXPECTED(info->r[bit] > 0))
280         {
281            double i_bit;
282            int bit_val = (i >> bit) & 0x01;
283
284            if (bit_val != 0)
285               i_bit   = v_on / info->r[bit];
286            else
287               i_bit = 0;
288            i_total += i_bit;
289         }
290      }
291      m_v_step[i] = i_total * r_total;
292   }
293}
294
295
296/************************************************************************
297*
298 * DST_DIODE_MIX  - Diode Mixer
299 *
300 * input[0]    - Input 0
301 * .....
302 *
303 * Dec 2004, D Renaud.
304 ************************************************************************/
305#define DST_DIODE_MIX_INP_OFFSET    0
306#define DST_DIODE_MIX__INP(addr)    DISCRETE_INPUT(DST_DIODE_MIX_INP_OFFSET + addr)
307
308DISCRETE_STEP(dst_diode_mix)
309{
310   double  val, max = 0;
311   int     addr;
312
313   for (addr = 0; addr < m_size; addr++)
314   {
315      val = DST_DIODE_MIX__INP(addr) - m_v_junction[addr];
316      if (val > max) max = val;
317   }
318   if (max < 0) max = 0;
319   set_output(0,  max);
320}
321
322DISCRETE_RESET(dst_diode_mix)
323{
324   DISCRETE_DECLARE_INFO(double)
325
326   int     addr;
327
328   m_size = this->active_inputs() - DST_DIODE_MIX_INP_OFFSET;
329   assert(m_size <= 8);
330
331   for (addr = 0; addr < m_size; addr++)
332   {
333      if (info == NULL)
334      {
335         /* setup default junction voltage */
336         m_v_junction[addr] = 0.5;
337      }
338      else
339      {
340         /* use supplied junction voltage */
341         m_v_junction[addr] = *info++;
342      }
343   }
344   this->step();
345}
346
347
348/************************************************************************
349 *
350 * DST_DIVIDE  - Programmable divider with enable
351 *
352 * input[0]    - Enable input value
353 * input[1]    - Channel0 input value
354 * input[2]    - Divisor
355 *
356 ************************************************************************/
357#define DST_DIVIDE__ENABLE  DISCRETE_INPUT(0)
358#define DST_DIVIDE__IN      DISCRETE_INPUT(1)
359#define DST_DIVIDE__DIV     DISCRETE_INPUT(2)
360
361DISCRETE_STEP(dst_divide)
362{
363   if(DST_DIVIDE__ENABLE)
364   {
365      if(DST_DIVIDE__DIV == 0)
366      {
367         set_output(0, DBL_MAX); /* Max out but don't break */
368         m_device->discrete_log("dst_divider_step() - Divide by Zero attempted in NODE_%02d.\n",this->index());
369      }
370      else
371      {
372            set_output(0, DST_DIVIDE__IN / DST_DIVIDE__DIV);
373      }
374   }
375   else
376   {
377      set_output(0, 0);
378   }
379}
380
381
382/************************************************************************
383 *
384 * DST_GAIN - This is a programmable gain module with enable function
385 *
386 * input[0]    - Channel0 input value
387 * input[1]    - Gain value
388 * input[2]    - Final addition offset
389 *
390 ************************************************************************/
391#define DST_GAIN__IN        DISCRETE_INPUT(0)
392#define DST_GAIN__GAIN      DISCRETE_INPUT(1)
393#define DST_GAIN__OFFSET    DISCRETE_INPUT(2)
394
395DISCRETE_STEP(dst_gain)
396{
397      set_output(0, DST_GAIN__IN * DST_GAIN__GAIN + DST_GAIN__OFFSET);
398}
399
400
401/************************************************************************
402 *
403 * DST_INTEGRATE - Integration circuits
404 *
405 * input[0] - Trigger 0
406 * input[1] - Trigger 1
407 *
408 * also passed discrete_integrate_info structure
409 *
410 * Mar 2004, D Renaud.
411 ************************************************************************/
412#define DST_INTEGRATE__TRG0 DISCRETE_INPUT(0)
413#define DST_INTEGRATE__TRG1 DISCRETE_INPUT(1)
414
415static int dst_trigger_function(int trig0, int trig1, int trig2, int function)
416{
417   int result = 1;
418   switch (function)
419   {
420      case DISC_OP_AMP_TRIGGER_FUNCTION_TRG0:
421         result = trig0;
422         break;
423      case DISC_OP_AMP_TRIGGER_FUNCTION_TRG0_INV:
424         result = !trig0;
425         break;
426      case DISC_OP_AMP_TRIGGER_FUNCTION_TRG1:
427         result = trig1;
428         break;
429      case DISC_OP_AMP_TRIGGER_FUNCTION_TRG1_INV:
430         result = !trig1;
431         break;
432      case DISC_OP_AMP_TRIGGER_FUNCTION_TRG2:
433         result = trig2;
434         break;
435      case DISC_OP_AMP_TRIGGER_FUNCTION_TRG2_INV:
436         result = !trig2;
437         break;
438      case DISC_OP_AMP_TRIGGER_FUNCTION_TRG01_AND:
439         result = trig0 && trig1;
440         break;
441      case DISC_OP_AMP_TRIGGER_FUNCTION_TRG01_NAND:
442         result = !(trig0 && trig1);
443         break;
444   }
445
446   return (result);
447}
448
449DISCRETE_STEP(dst_integrate)
450{
451   DISCRETE_DECLARE_INFO(discrete_integrate_info)
452
453   int     trig0, trig1;
454   double  i_neg = 0;  /* current into - input */
455   double  i_pos = 0;  /* current into + input */
456
457   switch (info->type)
458   {
459      case DISC_INTEGRATE_OP_AMP_1:
460         if (DST_INTEGRATE__TRG0 != 0)
461         {
462            /* This forces the cap to completely charge,
463             * and the output to go to it's max value.
464             */
465            m_v_out = m_v_max_out;
466            set_output(0, m_v_out);
467            return;
468         }
469         m_v_out -= m_change;
470         break;
471
472      case DISC_INTEGRATE_OP_AMP_1 | DISC_OP_AMP_IS_NORTON:
473         i_neg = m_v_max_in / info->r1;
474         i_pos = (DST_INTEGRATE__TRG0 - OP_AMP_NORTON_VBE) / info->r2;
475         if (i_pos < 0) i_pos = 0;
476         m_v_out += (i_pos - i_neg) / this->sample_rate() / info->c;
477         break;
478
479      case DISC_INTEGRATE_OP_AMP_2 | DISC_OP_AMP_IS_NORTON:
480         trig0  = (int)DST_INTEGRATE__TRG0;
481         trig1  = (int)DST_INTEGRATE__TRG1;
482         i_neg  = dst_trigger_function(trig0, trig1, 0, info->f0) ? m_v_max_in_d / info->r1 : 0;
483         i_pos  = dst_trigger_function(trig0, trig1, 0, info->f1) ? m_v_max_in / info->r2 : 0;
484         i_pos += dst_trigger_function(trig0, trig1, 0, info->f2) ? m_v_max_in_d / info->r3 : 0;
485         m_v_out += (i_pos - i_neg) / this->sample_rate() / info->c;
486         break;
487   }
488
489   /* Clip the output. */
490   if (m_v_out < 0) m_v_out = 0;
491   if (m_v_out > m_v_max_out) m_v_out = m_v_max_out;
492
493   set_output(0, m_v_out);
494}
495
496DISCRETE_RESET(dst_integrate)
497{
498   DISCRETE_DECLARE_INFO(discrete_integrate_info)
499
500   double  i, v;
501
502   if (info->type & DISC_OP_AMP_IS_NORTON)
503   {
504      m_v_max_out  = info->vP - OP_AMP_NORTON_VBE;
505      m_v_max_in   = info->v1 - OP_AMP_NORTON_VBE;
506      m_v_max_in_d = m_v_max_in - OP_AMP_NORTON_VBE;
507   }
508   else
509   {
510      m_v_max_out =  info->vP - OP_AMP_VP_RAIL_OFFSET;
511
512      v = info->v1 * info->r3 / (info->r2 + info->r3);    /* vRef */
513      v = info->v1 - v;   /* actual charging voltage */
514      i = v / info->r1;
515      m_change = i / this->sample_rate() / info->c;
516   }
517   m_v_out = 0;
518   set_output(0, m_v_out);
519}
520
521
522/************************************************************************
523 *
524 * DST_LOGIC_INV - Logic invertor gate implementation
525 *
526 * input[0]    - Enable
527 * input[1]    - input[0] value
528 *
529 ************************************************************************/
530#define DST_LOGIC_INV__IN       DISCRETE_INPUT(0)
531
532DISCRETE_STEP(dst_logic_inv)
533{
534   set_output(0,  DST_LOGIC_INV__IN ? 0.0 : 1.0);
535}
536
537/************************************************************************
538 *
539 * DST_BITS_DECODE - Decode Bits from input node
540 *
541 ************************************************************************/
542#define DST_BITS_DECODE__IN     DISCRETE_INPUT(0)
543#define DST_BITS_DECODE__FROM   DISCRETE_INPUT(1)
544#define DST_BITS_DECODE__TO     DISCRETE_INPUT(2)
545#define DST_BITS_DECODE__VOUT   DISCRETE_INPUT(3)
546
547DISCRETE_STEP(dst_bits_decode)
548{
549   int new_val = DST_BITS_DECODE__IN;
550   int last_val = m_last_val;
551   int last_had_x_time = m_last_had_x_time;
552
553   if (last_val != new_val || last_had_x_time)
554   {
555      int i, new_bit, last_bit, last_bit_had_x_time, bit_changed;
556      double x_time = DST_BITS_DECODE__IN - new_val;
557      int from = m_from;
558      int count = m_count;
559      int decode_x_time = m_decode_x_time;
560      int has_x_time = x_time > 0 ? 1 : 0;
561      double out = 0;
562      double v_out = DST_BITS_DECODE__VOUT;
563
564      for (i = 0; i < count; i++ )
565      {
566         new_bit = (new_val >> (i + from)) & 1;
567         last_bit = (last_val >> (i + from)) & 1;
568         last_bit_had_x_time = (last_had_x_time >> (i + from)) & 1;
569         bit_changed = last_bit != new_bit ? 1 : 0;
570
571         if (!bit_changed && !last_bit_had_x_time)
572            continue;
573
574         if (decode_x_time)
575         {
576            out = new_bit;
577            if (bit_changed)
578               out += x_time;
579         }
580         else
581         {
582            out = v_out;
583            if (has_x_time && bit_changed)
584            {
585               if (new_bit)
586                  out *= x_time;
587               else
588                  out *= (1.0 - x_time);
589            }
590            else
591               out *= new_bit;
592         }
593         set_output(i, out);
594         if (has_x_time && bit_changed)
595            /* set */
596            m_last_had_x_time |= 1 << (i + from);
597         else
598            /* clear */
599            m_last_had_x_time &= ~(1 << (i + from));
600      }
601      m_last_val = new_val;
602   }
603}
604
605DISCRETE_RESET(dst_bits_decode)
606{
607   m_from = DST_BITS_DECODE__FROM;
608   m_count = DST_BITS_DECODE__TO - m_from + 1;
609   if (DST_BITS_DECODE__VOUT == 0)
610      m_decode_x_time = 1;
611   else
612      m_decode_x_time = 0;
613   m_last_had_x_time = 0;
614
615   this->step();
616}
617
618
619/************************************************************************
620 *
621 * DST_LOGIC_AND - Logic AND gate implementation
622 *
623 * input[0]    - input[0] value
624 * input[1]    - input[1] value
625 * input[2]    - input[2] value
626 * input[3]    - input[3] value
627 *
628 ************************************************************************/
629#define DST_LOGIC_AND__IN0      DISCRETE_INPUT(0)
630#define DST_LOGIC_AND__IN1      DISCRETE_INPUT(1)
631#define DST_LOGIC_AND__IN2      DISCRETE_INPUT(2)
632#define DST_LOGIC_AND__IN3      DISCRETE_INPUT(3)
633
634DISCRETE_STEP(dst_logic_and)
635{
636   set_output(0,  (DST_LOGIC_AND__IN0 && DST_LOGIC_AND__IN1 && DST_LOGIC_AND__IN2 && DST_LOGIC_AND__IN3)? 1.0 : 0.0);
637}
638
639/************************************************************************
640 *
641 * DST_LOGIC_NAND - Logic NAND gate implementation
642 *
643 * input[0]    - input[0] value
644 * input[1]    - input[1] value
645 * input[2]    - input[2] value
646 * input[3]    - input[3] value
647 *
648 ************************************************************************/
649#define DST_LOGIC_NAND__IN0     DISCRETE_INPUT(0)
650#define DST_LOGIC_NAND__IN1     DISCRETE_INPUT(1)
651#define DST_LOGIC_NAND__IN2     DISCRETE_INPUT(2)
652#define DST_LOGIC_NAND__IN3     DISCRETE_INPUT(3)
653
654DISCRETE_STEP(dst_logic_nand)
655{
656   set_output(0, (DST_LOGIC_NAND__IN0 && DST_LOGIC_NAND__IN1 && DST_LOGIC_NAND__IN2 && DST_LOGIC_NAND__IN3)? 0.0 : 1.0);
657}
658
659/************************************************************************
660 *
661 * DST_LOGIC_OR  - Logic OR  gate implementation
662 *
663 * input[0]    - input[0] value
664 * input[1]    - input[1] value
665 * input[2]    - input[2] value
666 * input[3]    - input[3] value
667 *
668 ************************************************************************/
669#define DST_LOGIC_OR__IN0       DISCRETE_INPUT(0)
670#define DST_LOGIC_OR__IN1       DISCRETE_INPUT(1)
671#define DST_LOGIC_OR__IN2       DISCRETE_INPUT(2)
672#define DST_LOGIC_OR__IN3       DISCRETE_INPUT(3)
673
674DISCRETE_STEP(dst_logic_or)
675{
676   set_output(0,  (DST_LOGIC_OR__IN0 || DST_LOGIC_OR__IN1 || DST_LOGIC_OR__IN2 || DST_LOGIC_OR__IN3) ? 1.0 : 0.0);
677}
678
679/************************************************************************
680 *
681 * DST_LOGIC_NOR - Logic NOR gate implementation
682 *
683 * input[0]    - input[0] value
684 * input[1]    - input[1] value
685 * input[2]    - input[2] value
686 * input[3]    - input[3] value
687 *
688 ************************************************************************/
689#define DST_LOGIC_NOR__IN0      DISCRETE_INPUT(0)
690#define DST_LOGIC_NOR__IN1      DISCRETE_INPUT(1)
691#define DST_LOGIC_NOR__IN2      DISCRETE_INPUT(2)
692#define DST_LOGIC_NOR__IN3      DISCRETE_INPUT(3)
693
694DISCRETE_STEP(dst_logic_nor)
695{
696   set_output(0,  (DST_LOGIC_NOR__IN0 || DST_LOGIC_NOR__IN1 || DST_LOGIC_NOR__IN2 || DST_LOGIC_NOR__IN3) ? 0.0 : 1.0);
697}
698
699/************************************************************************
700 *
701 * DST_LOGIC_XOR - Logic XOR gate implementation
702 *
703 * input[0]    - input[0] value
704 * input[1]    - input[1] value
705 *
706 ************************************************************************/
707#define DST_LOGIC_XOR__IN0      DISCRETE_INPUT(0)
708#define DST_LOGIC_XOR__IN1      DISCRETE_INPUT(1)
709
710DISCRETE_STEP(dst_logic_xor)
711{
712   set_output(0,  ((DST_LOGIC_XOR__IN0 && !DST_LOGIC_XOR__IN1) || (!DST_LOGIC_XOR__IN0 && DST_LOGIC_XOR__IN1)) ? 1.0 : 0.0);
713}
714
715/************************************************************************
716 *
717 * DST_LOGIC_NXOR - Logic NXOR gate implementation
718 *
719 * input[0]    - input[0] value
720 * input[1]    - input[1] value
721 *
722 ************************************************************************/
723#define DST_LOGIC_XNOR__IN0     DISCRETE_INPUT(0)
724#define DST_LOGIC_XNOR__IN1     DISCRETE_INPUT(1)
725
726DISCRETE_STEP(dst_logic_nxor)
727{
728   set_output(0,  ((DST_LOGIC_XNOR__IN0 && !DST_LOGIC_XNOR__IN1) || (!DST_LOGIC_XNOR__IN0 && DST_LOGIC_XNOR__IN1)) ? 0.0 : 1.0);
729}
730
731
732/************************************************************************
733 *
734 * DST_LOGIC_DFF - Standard D-type flip-flop implementation
735 *
736 * input[0]    - /Reset
737 * input[1]    - /Set
738 * input[2]    - clock
739 * input[3]    - data
740 *
741 ************************************************************************/
742#define DST_LOGIC_DFF__RESET    !DISCRETE_INPUT(0)
743#define DST_LOGIC_DFF__SET      !DISCRETE_INPUT(1)
744#define DST_LOGIC_DFF__CLOCK     DISCRETE_INPUT(2)
745#define DST_LOGIC_DFF__DATA      DISCRETE_INPUT(3)
746
747DISCRETE_STEP(dst_logic_dff)
748{
749   int clk = (int)DST_LOGIC_DFF__CLOCK;
750
751   if (DST_LOGIC_DFF__RESET)
752      set_output(0,  0);
753   else if (DST_LOGIC_DFF__SET)
754      set_output(0,  1);
755   else if (!m_last_clk && clk)    /* low to high */
756      set_output(0,  DST_LOGIC_DFF__DATA);
757   m_last_clk = clk;
758}
759
760DISCRETE_RESET(dst_logic_dff)
761{
762   m_last_clk = 0;
763   set_output(0,  0);
764}
765
766
767/************************************************************************
768 *
769 * DST_LOGIC_JKFF - Standard JK-type flip-flop implementation
770 *
771 * input[0]    - /Reset
772 * input[1]    - /Set
773 * input[2]    - clock
774 * input[3]    - J
775 * input[4]    - K
776 *
777 ************************************************************************/
778#define DST_LOGIC_JKFF__RESET   !DISCRETE_INPUT(0)
779#define DST_LOGIC_JKFF__SET     !DISCRETE_INPUT(1)
780#define DST_LOGIC_JKFF__CLOCK    DISCRETE_INPUT(2)
781#define DST_LOGIC_JKFF__J        DISCRETE_INPUT(3)
782#define DST_LOGIC_JKFF__K        DISCRETE_INPUT(4)
783
784DISCRETE_STEP(dst_logic_jkff)
785{
786   int clk = (int)DST_LOGIC_JKFF__CLOCK;
787   int j   = (int)DST_LOGIC_JKFF__J;
788   int k   = (int)DST_LOGIC_JKFF__K;
789
790   if (DST_LOGIC_JKFF__RESET)
791      m_v_out = 0;
792   else if (DST_LOGIC_JKFF__SET)
793      m_v_out = 1;
794   else if (m_last_clk && !clk)    /* high to low */
795   {
796      if (!j)
797      {
798         /* J=0, K=0 - Hold */
799         if (k)
800            /* J=0, K=1 - Reset */
801            m_v_out = 0;
802      }
803      else
804      {
805         if (!k)
806            /* J=1, K=0 - Set */
807            m_v_out = 1;
808         else
809            /* J=1, K=1 - Toggle */
810            m_v_out = !(int)m_v_out;
811      }
812   }
813   m_last_clk = clk;
814   set_output(0, m_v_out);
815}
816
817DISCRETE_RESET(dst_logic_jkff)
818{
819   m_last_clk = 0;
820   m_v_out = 0;
821   set_output(0, m_v_out);
822}
823
824/************************************************************************
825 *
826 * DST_LOGIC_SHIFT - Shift Register implementation
827 *
828 ************************************************************************/
829#define DST_LOGIC_SHIFT__IN         DISCRETE_INPUT(0)
830#define DST_LOGIC_SHIFT__RESET      DISCRETE_INPUT(1)
831#define DST_LOGIC_SHIFT__CLK        DISCRETE_INPUT(2)
832#define DST_LOGIC_SHIFT__SIZE       DISCRETE_INPUT(3)
833#define DST_LOGIC_SHIFT__OPTIONS    DISCRETE_INPUT(4)
834
835DISCRETE_STEP(dst_logic_shift)
836{
837   double  cycles;
838   double  ds_clock;
839   int     clock = 0, inc = 0;
840
841   int input_bit = (DST_LOGIC_SHIFT__IN != 0) ? 1 : 0;
842   ds_clock = DST_LOGIC_SHIFT__CLK;
843   if (m_clock_type == DISC_CLK_IS_FREQ)
844   {
845      /* We need to keep clocking the internal clock even if in reset. */
846      cycles = (m_t_left + this->sample_time()) * ds_clock;
847      inc    = (int)cycles;
848      m_t_left = (cycles - inc) / ds_clock;
849   }
850   else
851   {
852      clock  = (int)ds_clock;
853   }
854
855   /* If reset enabled then set output to the reset value.  No x_time in reset. */
856   if(((DST_LOGIC_SHIFT__RESET == 0) ? 0 : 1) == m_reset_on_high)
857   {
858      m_shift_data = 0;
859      set_output(0,  0);
860      return;
861   }
862
863   /* increment clock */
864   switch (m_clock_type)
865   {
866      case DISC_CLK_ON_F_EDGE:
867      case DISC_CLK_ON_R_EDGE:
868         /* See if the clock has toggled to the proper edge */
869         clock = (clock != 0);
870         if (m_last != clock)
871         {
872            m_last = clock;
873            if (m_clock_type == clock)
874            {
875               /* Toggled */
876               inc = 1;
877            }
878         }
879         break;
880
881      case DISC_CLK_BY_COUNT:
882         /* Clock number of times specified. */
883         inc = clock;
884         break;
885   }
886
887   if (inc > 0)
888   {
889      if (m_shift_r)
890      {
891         m_shift_data >>= 1;
892         m_shift_data |= input_bit << ((int)DST_LOGIC_SHIFT__SIZE - 1);
893         inc--;
894         m_shift_data >>= inc;
895      }
896      else
897      {
898         m_shift_data <<= 1;
899         m_shift_data |= input_bit;
900         inc--;
901         m_shift_data <<= inc;
902      }
903      m_shift_data &= m_bit_mask;
904   }
905
906   set_output(0,  m_shift_data);
907}
908
909DISCRETE_RESET(dst_logic_shift)
910{
911   m_bit_mask = (1 << (int)DST_LOGIC_SHIFT__SIZE) - 1;
912   m_clock_type = (int)DST_LOGIC_SHIFT__OPTIONS & DISC_CLK_MASK;
913   m_reset_on_high = ((int)DST_LOGIC_SHIFT__OPTIONS & DISC_LOGIC_SHIFT__RESET_H) ? 1 : 0;
914   m_shift_r = ((int)DST_LOGIC_SHIFT__OPTIONS & DISC_LOGIC_SHIFT__RIGHT)  ? 1 : 0;
915
916   m_t_left  = 0;
917   m_last = 0;
918   m_shift_data   = 0;
919   set_output(0, 0);
920}
921
922/************************************************************************
923 *
924 * DST_LOOKUP_TABLE  - Return value from lookup table
925 *
926 * input[0]    - Input 1
927 * input[1]    - Table size
928 *
929 * Also passed address of the lookup table
930 *
931 * Feb 2007, D Renaud.
932 ************************************************************************/
933#define DST_LOOKUP_TABLE__IN        DISCRETE_INPUT(0)
934#define DST_LOOKUP_TABLE__SIZE      DISCRETE_INPUT(1)
935
936DISCRETE_STEP(dst_lookup_table)
937{
938   DISCRETE_DECLARE_INFO(double)
939
940   int addr = DST_LOOKUP_TABLE__IN;
941
942   if (addr < 0 || addr >= DST_LOOKUP_TABLE__SIZE)
943      set_output(0,  0);
944   else
945      set_output(0,  info[addr]);
946}
947
948
949/************************************************************************
950 *
951 * DST_MIXER  - Mixer/Gain stage
952 *
953 * input[0]    - Enable input value
954 * input[1]    - Input 1
955 * input[2]    - Input 2
956 * input[3]    - Input 3
957 * input[4]    - Input 4
958 * input[5]    - Input 5
959 * input[6]    - Input 6
960 * input[7]    - Input 7
961 * input[8]    - Input 8
962 *
963 * Also passed discrete_mixer_info structure
964 *
965 * Mar 2004, D Renaud.
966 ************************************************************************/
967/*
968 * The input resistors can be a combination of static values and nodes.
969 * If a node is used then its value is in series with the static value.
970 * Also if a node is used and its value is 0, then that means the
971 * input is disconnected from the circuit.
972 *
973 * There are 3 basic types of mixers, defined by the 2 types.  The
974 * op amp mixer is further defined by the prescence of rI.  This is a
975 * brief explanation.
976 *
977 * DISC_MIXER_IS_RESISTOR
978 * The inputs are high pass filtered if needed, using (rX || rF) * cX.
979 * Then Millman is used for the voltages.
980 * r = (1/rF + 1/r1 + 1/r2...)
981 * i = (v1/r1 + v2/r2...)
982 * v = i * r
983 *
984 * DISC_MIXER_IS_OP_AMP - no rI
985 * This is just a summing circuit.
986 * The inputs are high pass filtered if needed, using rX * cX.
987 * Then a modified Millman is used for the voltages.
988 * i = ((vRef - v1)/r1 + (vRef - v2)/r2...)
989 * v = i * rF
990 *
991 * DISC_MIXER_IS_OP_AMP_WITH_RI
992 * The inputs are high pass filtered if needed, using (rX + rI) * cX.
993 * Then Millman is used for the voltages including vRef/rI.
994 * r = (1/rI + 1/r1 + 1/r2...)
995 * i = (vRef/rI + v1/r1 + v2/r2...)
996 * The voltage is then modified by an inverting amp formula.
997 * v = vRef + (rF/rI) * (vRef - (i * r))
998 */
999#define DST_MIXER__ENABLE       DISCRETE_INPUT(0)
1000#define DST_MIXER__IN(bit)      DISCRETE_INPUT(bit + 1)
1001
1002DISCRETE_STEP(dst_mixer)
1003{
1004   DISCRETE_DECLARE_INFO(discrete_mixer_desc)
1005
1006   double  v, vTemp, r_total, rTemp, rTemp2 = 0;
1007   double  i = 0;      /* total current of inputs */
1008   int     bit, connected;
1009
1010   /* put commonly used stuff in local variables for speed */
1011   int     r_node_bit_flag = m_r_node_bit_flag;
1012   int     c_bit_flag = m_c_bit_flag;
1013   int     bit_mask = 1;
1014   int     has_rF = (info->rF != 0);
1015   int     type = m_type;
1016   double  v_ref = info->vRef;
1017   double  rI = info->rI;
1018
1019   if (EXPECTED(DST_MIXER__ENABLE))
1020   {
1021      r_total = m_r_total;
1022
1023      if (UNEXPECTED(m_r_node_bit_flag != 0))
1024      {
1025         /* loop and do any high pass filtering for connected caps */
1026         /* but first see if there is an r_node for the current path */
1027         /* if so, then the exponents need to be re-calculated */
1028         for (bit = 0; bit < m_size; bit++)
1029         {
1030            rTemp     = info->r[bit];
1031            connected = 1;
1032            vTemp     = DST_MIXER__IN(bit);
1033
1034            /* is there a resistor? */
1035            if (r_node_bit_flag & bit_mask)
1036            {
1037               /* a node has the possibility of being disconnected from the circuit. */
1038               if (*m_r_node[bit] == 0)
1039                  connected = 0;
1040               else
1041               {
1042                  /* value currently holds resistance */
1043                  rTemp   += *m_r_node[bit];
1044                  r_total += 1.0 / rTemp;
1045                  /* is there a capacitor? */
1046                  if (c_bit_flag & bit_mask)
1047                  {
1048                     switch (type)
1049                     {
1050                        case DISC_MIXER_IS_RESISTOR:
1051                           /* is there an rF? */
1052                           if (has_rF)
1053                           {
1054                              rTemp2 = RES_2_PARALLEL(rTemp, info->rF);
1055                              break;
1056                           }
1057                           /* else, fall through and just use the resistor value */
1058                        case DISC_MIXER_IS_OP_AMP:
1059                           rTemp2 = rTemp;
1060                           break;
1061                        case DISC_MIXER_IS_OP_AMP_WITH_RI:
1062                           rTemp2 = rTemp + rI;
1063                           break;
1064                     }
1065                     /* Re-calculate exponent if resistor is a node and has changed value */
1066                     if (*m_r_node[bit] != m_r_last[bit])
1067                     {
1068                        m_exponent_rc[bit] =  RC_CHARGE_EXP(rTemp2 * info->c[bit]);
1069                        m_r_last[bit] = *m_r_node[bit];
1070                     }
1071                  }
1072               }
1073            }
1074
1075            if (connected)
1076            {
1077               /* is there a capacitor? */
1078               if (c_bit_flag & bit_mask)
1079               {
1080                  /* do input high pass filtering if needed. */
1081                  m_v_cap[bit] += (vTemp - v_ref - m_v_cap[bit]) * m_exponent_rc[bit];
1082                  vTemp -= m_v_cap[bit];
1083               }
1084               i += ((type == DISC_MIXER_IS_OP_AMP) ? v_ref - vTemp : vTemp) / rTemp;
1085            }
1086         bit_mask = bit_mask << 1;
1087         }
1088      }
1089      else if (UNEXPECTED(c_bit_flag != 0))
1090      {
1091         /* no r_nodes, so just do high pass filtering */
1092         for (bit = 0; bit < m_size; bit++)
1093         {
1094            vTemp = DST_MIXER__IN(bit);
1095
1096            if (c_bit_flag & (1 << bit))
1097            {
1098               /* do input high pass filtering if needed. */
1099               m_v_cap[bit] += (vTemp - v_ref - m_v_cap[bit]) * m_exponent_rc[bit];
1100               vTemp -= m_v_cap[bit];
1101            }
1102            i += ((type == DISC_MIXER_IS_OP_AMP) ? v_ref - vTemp : vTemp) / info->r[bit];
1103         }
1104      }
1105      else
1106      {
1107         /* no r_nodes or c_nodes, mixing only */
1108         if (UNEXPECTED(type == DISC_MIXER_IS_OP_AMP))
1109         {
1110            for (bit = 0; bit < m_size; bit++)
1111               i += ( v_ref - DST_MIXER__IN(bit) ) / info->r[bit];
1112         }
1113         else
1114         {
1115            for (bit = 0; bit < m_size; bit++)
1116               i += DST_MIXER__IN(bit) / info->r[bit];
1117         }
1118      }
1119
1120      if (UNEXPECTED(type == DISC_MIXER_IS_OP_AMP_WITH_RI))
1121         i += v_ref / rI;
1122
1123      r_total = 1.0 / r_total;
1124
1125      /* If resistor network or has rI then Millman is used.
1126       * If op-amp then summing formula is used. */
1127      v = i * ((type == DISC_MIXER_IS_OP_AMP) ? info->rF : r_total);
1128
1129      if (UNEXPECTED(type == DISC_MIXER_IS_OP_AMP_WITH_RI))
1130         v = v_ref + (m_gain * (v_ref - v));
1131
1132      /* Do the low pass filtering for cF */
1133      if (EXPECTED(info->cF != 0))
1134      {
1135         if (UNEXPECTED(r_node_bit_flag != 0))
1136         {
1137            /* Re-calculate exponent if resistor nodes are used */
1138            m_exponent_c_f =  RC_CHARGE_EXP(r_total * info->cF);
1139         }
1140         m_v_cap_f += (v - v_ref - m_v_cap_f) * m_exponent_c_f;
1141         v = m_v_cap_f;
1142      }
1143
1144      /* Do the high pass filtering for cAmp */
1145      if (EXPECTED(info->cAmp != 0))
1146      {
1147         m_v_cap_amp += (v - m_v_cap_amp) * m_exponent_c_amp;
1148         v -= m_v_cap_amp;
1149      }
1150      set_output(0,  v * info->gain);
1151   }
1152   else
1153   {
1154      set_output(0,  0);
1155   }
1156}
1157
1158
1159DISCRETE_RESET(dst_mixer)
1160{
1161   DISCRETE_DECLARE_INFO(discrete_mixer_desc)
1162
1163   int     bit;
1164   double  rTemp = 0;
1165
1166   /* link to r_node outputs */
1167   m_r_node_bit_flag = 0;
1168   for (bit = 0; bit < 8; bit++)
1169   {
1170      m_r_node[bit] = m_device->node_output_ptr(info->r_node[bit]);
1171      if (m_r_node[bit] != NULL)
1172      {
1173         m_r_node_bit_flag |= 1 << bit;
1174      }
1175
1176      /* flag any caps */
1177      if (info->c[bit] != 0)
1178         m_c_bit_flag |= 1 << bit;
1179   }
1180
1181   m_size = this->active_inputs() - 1;
1182
1183   /*
1184    * THERE IS NO ERROR CHECKING!!!!!!!!!
1185    * If you pass a bad ladder table
1186    * then you deserve a crash.
1187    */
1188
1189   m_type = info->type;
1190   if ((info->type == DISC_MIXER_IS_OP_AMP) && (info->rI != 0))
1191      m_type = DISC_MIXER_IS_OP_AMP_WITH_RI;
1192
1193   /*
1194    * Calculate the total of all resistors in parallel.
1195    * This is the combined resistance of the voltage sources.
1196    * Also calculate the exponents while we are here.
1197    */
1198   m_r_total = 0;
1199   for(bit = 0; bit < m_size; bit++)
1200   {
1201      if ((info->r[bit] != 0) && !info->r_node[bit] )
1202      {
1203         m_r_total += 1.0 / info->r[bit];
1204      }
1205
1206      m_v_cap[bit]       = 0;
1207      m_exponent_rc[bit] = 0;
1208      if ((info->c[bit] != 0)  && !info->r_node[bit])
1209      {
1210         switch (m_type)
1211         {
1212            case DISC_MIXER_IS_RESISTOR:
1213               /* is there an rF? */
1214               if (info->rF != 0)
1215               {
1216                  rTemp = 1.0 / ((1.0 / info->r[bit]) + (1.0 / info->rF));
1217                  break;
1218               }
1219               /* else, fall through and just use the resistor value */
1220            case DISC_MIXER_IS_OP_AMP:
1221               rTemp = info->r[bit];
1222               break;
1223            case DISC_MIXER_IS_OP_AMP_WITH_RI:
1224               rTemp = info->r[bit] + info->rI;
1225               break;
1226         }
1227         /* Setup filter constants */
1228         m_exponent_rc[bit] = RC_CHARGE_EXP(rTemp * info->c[bit]);
1229      }
1230   }
1231
1232   if (info->rF != 0)
1233   {
1234      if (m_type == DISC_MIXER_IS_RESISTOR) m_r_total += 1.0 / info->rF;
1235   }
1236   if (m_type == DISC_MIXER_IS_OP_AMP_WITH_RI) m_r_total += 1.0 / info->rI;
1237
1238   m_v_cap_f      = 0;
1239   m_exponent_c_f = 0;
1240   if (info->cF != 0)
1241   {
1242      /* Setup filter constants */
1243      m_exponent_c_f = RC_CHARGE_EXP(((info->type == DISC_MIXER_IS_OP_AMP) ? info->rF : (1.0 / m_r_total)) * info->cF);
1244   }
1245
1246   m_v_cap_amp      = 0;
1247   m_exponent_c_amp = 0;
1248   if (info->cAmp != 0)
1249   {
1250      /* Setup filter constants */
1251      /* We will use 100k ohms as an average final stage impedance. */
1252      /* Your amp/speaker system will have more effect on incorrect filtering then any value used here. */
1253      m_exponent_c_amp = RC_CHARGE_EXP(RES_K(100) * info->cAmp);
1254   }
1255
1256   if (m_type == DISC_MIXER_IS_OP_AMP_WITH_RI) m_gain = info->rF / info->rI;
1257
1258   set_output(0,  0);
1259}
1260
1261
1262/************************************************************************
1263 *
1264 * DST_MULTIPLEX - 1 of x multiplexer/switch
1265 *
1266 * input[0]    - switch position
1267 * input[1]    - input[0]
1268 * input[2]    - input[1]
1269 * .....
1270 *
1271 * Dec 2004, D Renaud.
1272 ************************************************************************/
1273#define DST_MULTIPLEX__ADDR         DISCRETE_INPUT(0)
1274#define DST_MULTIPLEX__INP(addr)    DISCRETE_INPUT(1 + addr)
1275
1276DISCRETE_STEP(dst_multiplex)
1277{
1278   int addr;
1279
1280   addr = DST_MULTIPLEX__ADDR; /* FP to INT */
1281   if ((addr >= 0) && (addr < m_size))
1282   {
1283      set_output(0,  DST_MULTIPLEX__INP(addr));
1284   }
1285   else
1286   {
1287      /* Bad address.  We will leave the output alone. */
1288      m_device->discrete_log("NODE_%02d - Address = %d. Out of bounds\n", this->index(), addr);
1289   }
1290}
1291
1292DISCRETE_RESET(dst_multiplex)
1293{
1294   m_size = this->active_inputs() - 1;
1295
1296   this->step();
1297}
1298
1299
1300/************************************************************************
1301 *
1302 * DST_ONESHOT - Usage of node_description values for one shot pulse
1303 *
1304 * input[0]    - Reset value
1305 * input[1]    - Trigger value
1306 * input[2]    - Amplitude value
1307 * input[3]    - Width of oneshot pulse
1308 * input[4]    - type R/F edge, Retriggerable?
1309 *
1310 * Complete re-write Jan 2004, D Renaud.
1311 ************************************************************************/
1312#define DST_ONESHOT__RESET  DISCRETE_INPUT(0)
1313#define DST_ONESHOT__TRIG   DISCRETE_INPUT(1)
1314#define DST_ONESHOT__AMP    DISCRETE_INPUT(2)
1315#define DST_ONESHOT__WIDTH  DISCRETE_INPUT(3)
1316#define DST_ONESHOT__TYPE   (int)DISCRETE_INPUT(4)
1317
1318DISCRETE_STEP(dst_oneshot)
1319{
1320   int trigger = (DST_ONESHOT__TRIG != 0);
1321
1322   /* If the state is triggered we will need to countdown later */
1323   int do_count = m_state;
1324
1325   if (UNEXPECTED(DST_ONESHOT__RESET))
1326   {
1327      /* Hold in Reset */
1328      set_output(0, 0);
1329      m_state  = 0;
1330   }
1331   else
1332   {
1333      /* are we at an edge? */
1334      if (UNEXPECTED(trigger != m_last_trig))
1335      {
1336         /* There has been a trigger edge */
1337         m_last_trig = trigger;
1338
1339         /* Is it the proper edge trigger */
1340         if ((m_type & DISC_ONESHOT_REDGE) ? trigger : !trigger)
1341         {
1342            if (!m_state)
1343            {
1344               /* We have first trigger */
1345               m_state     = 1;
1346               set_output(0, (m_type & DISC_OUT_ACTIVE_LOW) ? 0 : DST_ONESHOT__AMP);
1347               m_countdown = DST_ONESHOT__WIDTH;
1348            }
1349            else
1350            {
1351               /* See if we retrigger */
1352               if (m_type & DISC_ONESHOT_RETRIG)
1353               {
1354                  /* Retrigger */
1355                  m_countdown = DST_ONESHOT__WIDTH;
1356                  do_count = 0;
1357               }
1358            }
1359         }
1360      }
1361
1362      if (UNEXPECTED(do_count))
1363      {
1364         m_countdown -= this->sample_time();
1365         if(m_countdown <= 0.0)
1366         {
1367            set_output(0, (m_type & DISC_OUT_ACTIVE_LOW) ? DST_ONESHOT__AMP : 0);
1368            m_countdown = 0;
1369            m_state     = 0;
1370         }
1371      }
1372   }
1373}
1374
1375
1376DISCRETE_RESET(dst_oneshot)
1377{
1378   m_countdown = 0;
1379   m_state     = 0;
1380
1381   m_last_trig = 0;
1382   m_type = DST_ONESHOT__TYPE;
1383
1384   set_output(0,  (m_type & DISC_OUT_ACTIVE_LOW) ? DST_ONESHOT__AMP : 0);
1385}
1386
1387
1388/************************************************************************
1389 *
1390 * DST_RAMP - Ramp up/down model usage
1391 *
1392 * input[0]    - Enable ramp
1393 * input[1]    - Ramp Reverse/Forward switch
1394 * input[2]    - Gradient, change/sec
1395 * input[3]    - Start value
1396 * input[4]    - End value
1397 * input[5]    - Clamp value when disabled
1398 *
1399 ************************************************************************/
1400#define DST_RAMP__ENABLE    DISCRETE_INPUT(0)
1401#define DST_RAMP__DIR       DISCRETE_INPUT(1)
1402#define DST_RAMP__GRAD      DISCRETE_INPUT(2)
1403#define DST_RAMP__START     DISCRETE_INPUT(3)
1404#define DST_RAMP__END       DISCRETE_INPUT(4)
1405#define DST_RAMP__CLAMP     DISCRETE_INPUT(5)
1406
1407DISCRETE_STEP(dst_ramp)
1408{
1409   if(DST_RAMP__ENABLE)
1410   {
1411      if (!m_last_en)
1412      {
1413         m_last_en = 1;
1414         m_v_out = DST_RAMP__START;
1415      }
1416      if(m_dir ? DST_RAMP__DIR : !DST_RAMP__DIR) m_v_out += m_step;
1417      else m_v_out -= m_step;
1418      /* Clamp to min/max */
1419      if(m_dir ? (m_v_out < DST_RAMP__START)
1420            : (m_v_out > DST_RAMP__START)) m_v_out = DST_RAMP__START;
1421      if(m_dir ? (m_v_out > DST_RAMP__END)
1422            : (m_v_out < DST_RAMP__END)) m_v_out = DST_RAMP__END;
1423   }
1424   else
1425   {
1426      m_last_en = 0;
1427      /* Disabled so clamp to output */
1428      m_v_out = DST_RAMP__CLAMP;
1429   }
1430
1431   set_output(0, m_v_out);
1432}
1433
1434DISCRETE_RESET(dst_ramp)
1435{
1436   m_v_out = DST_RAMP__CLAMP;
1437   m_step    = DST_RAMP__GRAD / this->sample_rate();
1438   m_dir     = ((DST_RAMP__END - DST_RAMP__START) == abs(DST_RAMP__END - DST_RAMP__START));
1439   m_last_en = 0;
1440}
1441
1442
1443/************************************************************************
1444 *
1445 * DST_SAMPHOLD - Sample & Hold Implementation
1446 *
1447 * input[0]    - input[0] value
1448 * input[1]    - clock node
1449 * input[2]    - clock type
1450 *
1451 ************************************************************************/
1452#define DST_SAMPHOLD__IN0       DISCRETE_INPUT(0)
1453#define DST_SAMPHOLD__CLOCK     DISCRETE_INPUT(1)
1454#define DST_SAMPHOLD__TYPE      DISCRETE_INPUT(2)
1455
1456DISCRETE_STEP(dst_samphold)
1457{
1458   switch(m_clocktype)
1459   {
1460      case DISC_SAMPHOLD_REDGE:
1461         /* Clock the whole time the input is rising */
1462         if (DST_SAMPHOLD__CLOCK > m_last_input) set_output(0,  DST_SAMPHOLD__IN0);
1463         break;
1464      case DISC_SAMPHOLD_FEDGE:
1465         /* Clock the whole time the input is falling */
1466         if(DST_SAMPHOLD__CLOCK < m_last_input) set_output(0,  DST_SAMPHOLD__IN0);
1467         break;
1468      case DISC_SAMPHOLD_HLATCH:
1469         /* Output follows input if clock != 0 */
1470         if( DST_SAMPHOLD__CLOCK) set_output(0,  DST_SAMPHOLD__IN0);
1471         break;
1472      case DISC_SAMPHOLD_LLATCH:
1473         /* Output follows input if clock == 0 */
1474         if (DST_SAMPHOLD__CLOCK == 0) set_output(0,  DST_SAMPHOLD__IN0);
1475         break;
1476      default:
1477         m_device->discrete_log("dst_samphold_step - Invalid clocktype passed");
1478         break;
1479   }
1480   /* Save the last value */
1481   m_last_input = DST_SAMPHOLD__CLOCK;
1482}
1483
1484DISCRETE_RESET(dst_samphold)
1485{
1486   set_output(0, 0);
1487   m_last_input = -1;
1488   /* Only stored in here to speed up and save casting in the step function */
1489   m_clocktype = (int)DST_SAMPHOLD__TYPE;
1490   this->step();
1491}
1492
1493
1494/************************************************************************
1495 *
1496 * DST_SWITCH - Programmable 2 pole switch module with enable function
1497 *
1498 * input[0]    - Enable input value
1499 * input[1]    - switch position
1500 * input[2]    - input[0]
1501 * input[3]    - input[1]
1502 *
1503 ************************************************************************/
1504#define DST_SWITCH__ENABLE  DISCRETE_INPUT(0)
1505#define DST_SWITCH__SWITCH  DISCRETE_INPUT(1)
1506#define DST_SWITCH__IN0     DISCRETE_INPUT(2)
1507#define DST_SWITCH__IN1     DISCRETE_INPUT(3)
1508
1509DISCRETE_STEP(dst_switch)
1510{
1511   if(DST_SWITCH__ENABLE)
1512   {
1513      set_output(0,  DST_SWITCH__SWITCH ? DST_SWITCH__IN1 : DST_SWITCH__IN0);
1514   }
1515   else
1516   {
1517      set_output(0,  0);
1518   }
1519}
1520
1521/************************************************************************
1522 *
1523 * DST_ASWITCH - Analog switch
1524 *
1525 * input[1]    - Control
1526 * input[2]    - Input
1527 * input[3]    - Threshold for enable
1528 *
1529 ************************************************************************/
1530#define DST_ASWITCH__CTRL       DISCRETE_INPUT(0)
1531#define DST_ASWITCH__IN         DISCRETE_INPUT(1)
1532#define DST_ASWITCH__THRESHOLD  DISCRETE_INPUT(2)
1533
1534
1535DISCRETE_STEP(dst_aswitch)
1536{
1537   set_output(0,  DST_ASWITCH__CTRL > DST_ASWITCH__THRESHOLD ? DST_ASWITCH__IN : 0);
1538}
1539
1540/************************************************************************
1541 *
1542 * DST_TRANSFORM - Programmable math module
1543 *
1544 * input[0]    - Channel0 input value
1545 * input[1]    - Channel1 input value
1546 * input[2]    - Channel2 input value
1547 * input[3]    - Channel3 input value
1548 * input[4]    - Channel4 input value
1549 *
1550 ************************************************************************/
1551#define MAX_TRANS_STACK 16
1552
1553struct double_stack {
1554public:
1555   double_stack() : p(&stk[0])  { }
1556   inline void push(double v)
1557   {
1558      //Store THEN increment
1559      assert(p <= &stk[MAX_TRANS_STACK-1]);
1560      *p++ = v;
1561   }
1562   inline double pop(void)
1563   {
1564      //decrement THEN read
1565      assert(p > &stk[0]);
1566      p--;
1567      return *p;
1568   }
1569private:
1570   double stk[MAX_TRANS_STACK];
1571   double *p;
1572};
1573
1574DISCRETE_STEP(dst_transform)
1575{
1576   double_stack    stack;
1577   double  top;
1578
1579   enum token *fPTR = &precomp[0];
1580
1581   top = HUGE_VAL;
1582
1583   while(*fPTR != TOK_END)
1584   {
1585      switch (*fPTR++)
1586      {
1587         case TOK_MULT:      top = stack.pop() * top;                    break;
1588         case TOK_DIV:       top = stack.pop() / top;                    break;
1589         case TOK_ADD:       top = stack.pop() + top;                    break;
1590         case TOK_MINUS:     top = stack.pop() - top;                    break;
1591         case TOK_0:         stack.push(top); top = I_IN0();             break;
1592         case TOK_1:         stack.push(top); top = I_IN1();             break;
1593         case TOK_2:         stack.push(top); top = I_IN2();             break;
1594         case TOK_3:         stack.push(top); top = I_IN3();             break;
1595         case TOK_4:         stack.push(top); top = I_IN4();             break;
1596         case TOK_DUP:       stack.push(top);                            break;
1597         case TOK_ABS:       top = fabs(top);                            break;  /* absolute value */
1598         case TOK_NEG:       top = -top;                                 break;  /* * -1 */
1599         case TOK_NOT:       top = !top;                                 break;  /* Logical NOT of Last Value */
1600         case TOK_EQUAL:     top = (int)stack.pop() == (int)top;         break;  /* Logical = */
1601         case TOK_GREATER:   top = (stack.pop() > top);                  break;  /* Logical > */
1602         case TOK_LESS:      top = (stack.pop() < top);                  break;  /* Logical < */
1603         case TOK_AND:       top = (int)stack.pop() & (int)top;          break;  /* Bitwise AND */
1604         case TOK_OR:        top = (int)stack.pop() | (int)top;          break;  /* Bitwise OR */
1605         case TOK_XOR:       top = (int)stack.pop() ^ (int)top;          break;  /* Bitwise XOR */
1606         case TOK_END:       break; /* please compiler */
1607      }
1608   }
1609   set_output(0,  top);
1610}
1611
1612DISCRETE_RESET(dst_transform)
1613{
1614   const char *fPTR = (const char *)this->custom_data();
1615   enum token *p = &precomp[0];
1616
1617   while(*fPTR != 0)
1618   {
1619      switch (*fPTR++)
1620      {
1621         case '*':   *p = TOK_MULT;      break;
1622         case '/':   *p = TOK_DIV;       break;
1623         case '+':   *p = TOK_ADD;       break;
1624         case '-':   *p = TOK_MINUS;     break;
1625         case '0':   *p = TOK_0;         break;
1626         case '1':   *p = TOK_1;         break;
1627         case '2':   *p = TOK_2;         break;
1628         case '3':   *p = TOK_3;         break;
1629         case '4':   *p = TOK_4;         break;
1630         case 'P':   *p = TOK_DUP;       break;
1631         case 'a':   *p = TOK_ABS;       break; /* absolute value */
1632         case 'i':   *p = TOK_NEG;       break; /* * -1 */
1633         case '!':   *p = TOK_NOT;       break; /* Logical NOT of Last Value */
1634         case '=':   *p = TOK_EQUAL;     break; /* Logical = */
1635         case '>':   *p = TOK_GREATER;   break; /* Logical > */
1636         case '<':   *p = TOK_LESS;      break; /* Logical < */
1637         case '&':   *p = TOK_AND;       break; /* Bitwise AND */
1638         case '|':   *p = TOK_OR;        break; /* Bitwise OR */
1639         case '^':   *p = TOK_XOR;       break; /* Bitwise XOR */
1640         default:
1641            m_device->discrete_log("dst_transform_step - Invalid function type/variable passed: %s",(const char *)this->custom_data());
1642            /* that is enough to fatalerror */
1643            fatalerror("dst_transform_step - Invalid function type/variable passed: %s\n", (const char *)this->custom_data());
1644            break;
1645      }
1646      p++;
1647   }
1648   *p = TOK_END;
1649}
1650
1651/************************************************************************
1652 *
1653 * DST_OP_AMP - op amp circuits
1654 *
1655 * input[0] - Enable
1656 * input[1] - Input 0
1657 * input[2] - Input 1
1658 *
1659 * also passed discrete_op_amp_info structure
1660 *
1661 * Mar 2007, D Renaud.
1662 ************************************************************************/
1663#define DST_OP_AMP__ENABLE  DISCRETE_INPUT(0)
1664#define DST_OP_AMP__INP0    DISCRETE_INPUT(1)
1665#define DST_OP_AMP__INP1    DISCRETE_INPUT(2)
1666
1667DISCRETE_STEP(dst_op_amp)
1668{
1669   DISCRETE_DECLARE_INFO(discrete_op_amp_info)
1670
1671   double i_pos = 0;
1672   double i_neg = 0;
1673   double i    = 0;
1674   double v_out;
1675
1676   if (DST_OP_AMP__ENABLE)
1677   {
1678      switch (info->type)
1679      {
1680         case DISC_OP_AMP_IS_NORTON:
1681            /* work out neg pin current */
1682            if  (m_has_r1)
1683            {
1684               i_neg = (DST_OP_AMP__INP0 - OP_AMP_NORTON_VBE) / info->r1;
1685               if (i_neg < 0) i_neg = 0;
1686            }
1687            i_neg += m_i_fixed;
1688
1689            /* work out neg pin current */
1690            i_pos = (DST_OP_AMP__INP1 - OP_AMP_NORTON_VBE) / info->r2;
1691            if (i_pos < 0) i_pos = 0;
1692
1693            /* work out current across r4 */
1694            i = i_pos - i_neg;
1695
1696            if (m_has_cap)
1697            {
1698               if (m_has_r4)
1699               {
1700                  /* voltage across r4 charging cap */
1701                  i *= info->r4;
1702                  /* exponential charge */
1703                  m_v_cap += (i - m_v_cap) * m_exponent;
1704               }
1705               else
1706                  /* linear charge */
1707                  m_v_cap += i / m_exponent;
1708               v_out = m_v_cap;
1709            }
1710            else
1711               if (m_has_r4)
1712                  v_out = i * info->r4;
1713               else
1714                  /* output just swings to rail when there is no r4 */
1715                  if (i > 0)
1716                     v_out = m_v_max;
1717                  else
1718                     v_out = 0;
1719
1720            /* clamp output */
1721            if (v_out > m_v_max) v_out = m_v_max;
1722            else if (v_out < info->vN) v_out = info->vN;
1723            m_v_cap = v_out;
1724
1725            set_output(0, v_out);
1726            break;
1727
1728         default:
1729            set_output(0, 0);
1730      }
1731   }
1732   else
1733      set_output(0, 0);
1734}
1735
1736DISCRETE_RESET(dst_op_amp)
1737{
1738   DISCRETE_DECLARE_INFO(discrete_op_amp_info)
1739
1740   m_has_r1 = info->r1 > 0;
1741   m_has_r4 = info->r4 > 0;
1742
1743   m_v_max = info->vP - OP_AMP_NORTON_VBE;
1744
1745   m_v_cap = 0;
1746   if (info->c > 0)
1747   {
1748      m_has_cap = 1;
1749      /* Setup filter constants */
1750      if (m_has_r4)
1751      {
1752         /* exponential charge */
1753         m_exponent = RC_CHARGE_EXP(info->r4 * info->c);
1754      }
1755      else
1756         /* linear charge */
1757         m_exponent = this->sample_rate() * info->c;
1758   }
1759
1760   if (info->r3 > 0)
1761      m_i_fixed = (info->vP - OP_AMP_NORTON_VBE) / info->r3;
1762   else
1763      m_i_fixed = 0;
1764}
1765
1766
1767/************************************************************************
1768 *
1769 * DST_OP_AMP_1SHT - op amp one shot circuits
1770 *
1771 * input[0] - Trigger
1772 *
1773 * also passed discrete_op_amp_1sht_info structure
1774 *
1775 * Mar 2007, D Renaud.
1776 ************************************************************************/
1777#define DST_OP_AMP_1SHT__TRIGGER    DISCRETE_INPUT(0)
1778
1779DISCRETE_STEP(dst_op_amp_1sht)
1780{
1781   DISCRETE_DECLARE_INFO(discrete_op_amp_1sht_info)
1782
1783   double i_pos;
1784   double i_neg;
1785   double v;
1786
1787   /* update trigger circuit */
1788   i_pos  = (DST_OP_AMP_1SHT__TRIGGER - m_v_cap2) / info->r2;
1789   i_pos += m_v_out / info->r5;
1790   m_v_cap2 += (DST_OP_AMP_1SHT__TRIGGER - m_v_cap2) * m_exponent2;
1791
1792   /* calculate currents and output */
1793   i_neg = (m_v_cap1 - OP_AMP_NORTON_VBE) / info->r3;
1794   if (i_neg < 0) i_neg = 0;
1795   i_neg += m_i_fixed;
1796
1797   if (i_pos > i_neg) m_v_out = m_v_max;
1798   else m_v_out = info->vN;
1799
1800   /* update c1 */
1801   /* rough value of voltage at anode of diode if discharging */
1802   v = m_v_out + 0.6;
1803   if (m_v_cap1 > m_v_out)
1804   {
1805      /* discharge */
1806      if (m_v_cap1 > v)
1807         /* immediate discharge through diode */
1808         m_v_cap1 = v;
1809      else
1810         /* discharge through r4 */
1811         m_v_cap1 += (m_v_out - m_v_cap1) * m_exponent1d;
1812   }
1813   else
1814      /* charge */
1815      m_v_cap1 += ((m_v_out - OP_AMP_NORTON_VBE) * m_r34ratio + OP_AMP_NORTON_VBE - m_v_cap1) * m_exponent1c;
1816
1817   set_output(0, m_v_out);
1818}
1819
1820DISCRETE_RESET(dst_op_amp_1sht)
1821{
1822   DISCRETE_DECLARE_INFO(discrete_op_amp_1sht_info)
1823
1824   m_exponent1c = RC_CHARGE_EXP(RES_2_PARALLEL(info->r3, info->r4) * info->c1);
1825   m_exponent1d = RC_CHARGE_EXP(info->r4 * info->c1);
1826   m_exponent2  = RC_CHARGE_EXP(info->r2 * info->c2);
1827   m_i_fixed  = (info->vP - OP_AMP_NORTON_VBE) / info->r1;
1828   m_v_cap1   = m_v_cap2 = 0;
1829   m_v_max    = info->vP - OP_AMP_NORTON_VBE;
1830   m_r34ratio = info->r3 / (info->r3 + info->r4);
1831}
1832
1833
1834/************************************************************************
1835 *
1836 * DST_TVCA_OP_AMP - trigged op-amp VCA
1837 *
1838 * input[0] - Trigger 0
1839 * input[1] - Trigger 1
1840 * input[2] - Trigger 2
1841 * input[3] - Input 0
1842 * input[4] - Input 1
1843 *
1844 * also passed discrete_op_amp_tvca_info structure
1845 *
1846 * Mar 2004, D Renaud.
1847 ************************************************************************/
1848#define DST_TVCA_OP_AMP__TRG0   DISCRETE_INPUT(0)
1849#define DST_TVCA_OP_AMP__TRG1   DISCRETE_INPUT(1)
1850#define DST_TVCA_OP_AMP__TRG2   DISCRETE_INPUT(2)
1851#define DST_TVCA_OP_AMP__INP0   DISCRETE_INPUT(3)
1852#define DST_TVCA_OP_AMP__INP1   DISCRETE_INPUT(4)
1853
1854DISCRETE_STEP(dst_tvca_op_amp)
1855{
1856   DISCRETE_DECLARE_INFO(discrete_op_amp_tvca_info)
1857
1858   int     trig0, trig1, trig2, f3;
1859   double  i2 = 0;     /* current through r2 */
1860   double  i3 = 0;     /* current through r3 */
1861   double  i_neg = 0;  /* current into - input */
1862   double  i_pos = 0;  /* current into + input */
1863   double  i_out = 0;  /* current at output */
1864
1865   double  v_out;
1866
1867   trig0 = (int)DST_TVCA_OP_AMP__TRG0;
1868   trig1 = (int)DST_TVCA_OP_AMP__TRG1;
1869   trig2 = (int)DST_TVCA_OP_AMP__TRG2;
1870   f3 = dst_trigger_function(trig0, trig1, trig2, info->f3);
1871
1872   if ((info->r2 != 0) && dst_trigger_function(trig0, trig1, trig2, info->f0))
1873      {
1874         /* r2 is present, so we assume Input 0 is connected and valid. */
1875         i2 = (DST_TVCA_OP_AMP__INP0 - OP_AMP_NORTON_VBE) / info->r2;
1876         if ( i2 < 0) i2 = 0;
1877      }
1878
1879   if ((info->r3 != 0) && dst_trigger_function(trig0, trig1, trig2, info->f1))
1880      {
1881         /* r2 is present, so we assume Input 1 is connected and valid. */
1882         /* Function F1 is not grounding the circuit. */
1883         i3 = (DST_TVCA_OP_AMP__INP1 - OP_AMP_NORTON_VBE) / info->r3;
1884         if ( i3 < 0) i3 = 0;
1885      }
1886
1887   /* Calculate current going in to - input. */
1888   i_neg = m_i_fixed + i2 + i3;
1889
1890   /* Update the c1 cap voltage. */
1891   if (dst_trigger_function(trig0, trig1, trig2, info->f2))
1892   {
1893      /* F2 is not grounding the circuit so we charge the cap. */
1894      m_v_cap1 += (m_v_trig[f3] - m_v_cap1) * m_exponent_c[f3];
1895   }
1896   else
1897   {
1898      /* F2 is at ground.  The diode blocks this so F2 and r5 are out of circuit.
1899       * So now the discharge rate is dependent upon F3.
1900       * If F3 is at ground then we discharge to 0V through r6.
1901       * If F3 is out of circuit then we discharge to OP_AMP_NORTON_VBE through r6+r7. */
1902      m_v_cap1 += ((f3 ? OP_AMP_NORTON_VBE : 0.0) - m_v_cap1) * m_exponent_d[f3];
1903   }
1904
1905   /* Calculate c1 current going in to + input. */
1906   i_pos = (m_v_cap1 - OP_AMP_NORTON_VBE) / m_r67;
1907   if ((i_pos < 0) || !f3) i_pos = 0;
1908
1909   /* Update the c2 cap voltage and current. */
1910   if (info->r9 != 0)
1911   {
1912      f3 = dst_trigger_function(trig0, trig1, trig2, info->f4);
1913      m_v_cap2 += ((f3 ? m_v_trig2 : 0) - m_v_cap2) * m_exponent2[f3];
1914      i_pos += m_v_cap2 / info->r9;
1915   }
1916
1917   /* Update the c3 cap voltage and current. */
1918   if (info->r11 != 0)
1919   {
1920      f3 = dst_trigger_function(trig0, trig1, trig2, info->f5);
1921      m_v_cap3 += ((f3 ? m_v_trig3 : 0) - m_v_cap3) * m_exponent3[f3];
1922      i_pos += m_v_cap3 / info->r11;
1923   }
1924
1925   /* Calculate output current. */
1926   i_out = i_pos - i_neg;
1927   if (i_out < 0) i_out = 0;
1928
1929   /* Convert to voltage for final output. */
1930   if (m_has_c4)
1931   {
1932      if (m_has_r4)
1933      {
1934         /* voltage across r4 charging cap */
1935         i_out *= info->r4;
1936         /* exponential charge */
1937         m_v_cap4 += (i_out - m_v_cap4) * m_exponent4;
1938      }
1939      else
1940      /* linear charge */
1941         m_v_cap4 += i_out / m_exponent4;
1942      if (m_v_cap4 < 0)
1943         m_v_cap4 = 0;
1944      v_out = m_v_cap4;
1945   }
1946   else
1947      v_out = i_out * info->r4;
1948
1949
1950
1951   /* Clip the output if needed. */
1952   if (v_out > m_v_out_max) v_out = m_v_out_max;
1953
1954   set_output(0, v_out);
1955}
1956
1957DISCRETE_RESET(dst_tvca_op_amp)
1958{
1959   DISCRETE_DECLARE_INFO(discrete_op_amp_tvca_info)
1960
1961   m_r67 = info->r6 + info->r7;
1962
1963   m_v_out_max = info->vP - OP_AMP_NORTON_VBE;
1964   /* This is probably overkill because R5 is usually much lower then r6 or r7,
1965    * but it is better to play it safe. */
1966   m_v_trig[0] = (info->v1 - 0.6) * RES_VOLTAGE_DIVIDER(info->r5, info->r6);
1967   m_v_trig[1] = (info->v1 - 0.6 - OP_AMP_NORTON_VBE) * RES_VOLTAGE_DIVIDER(info->r5, m_r67) + OP_AMP_NORTON_VBE;
1968   m_i_fixed   = m_v_out_max / info->r1;
1969
1970   m_v_cap1 = 0;
1971   /* Charge rate through r5 */
1972   /* There can be a different charge rates depending on function F3. */
1973   m_exponent_c[0] = RC_CHARGE_EXP(RES_2_PARALLEL(info->r5, info->r6) * info->c1);
1974   m_exponent_c[1] = RC_CHARGE_EXP(RES_2_PARALLEL(info->r5, m_r67) * info->c1);
1975   /* Discharge rate through r6 + r7 */
1976   m_exponent_d[1] = RC_CHARGE_EXP(m_r67 * info->c1);
1977   /* Discharge rate through r6 */
1978   if (info->r6 != 0)
1979   {
1980      m_exponent_d[0] = RC_CHARGE_EXP(info->r6 * info->c1);
1981   }
1982   m_v_cap2       = 0;
1983   m_v_trig2      = (info->v2 - 0.6 - OP_AMP_NORTON_VBE) * RES_VOLTAGE_DIVIDER(info->r8, info->r9);
1984   m_exponent2[0] = RC_CHARGE_EXP(info->r9 * info->c2);
1985   m_exponent2[1] = RC_CHARGE_EXP(RES_2_PARALLEL(info->r8, info->r9) * info->c2);
1986   m_v_cap3       = 0;
1987   m_v_trig3      = (info->v3 - 0.6 - OP_AMP_NORTON_VBE) * RES_VOLTAGE_DIVIDER(info->r10, info->r11);
1988   m_exponent3[0] = RC_CHARGE_EXP(info->r11 * info->c3);
1989   m_exponent3[1] = RC_CHARGE_EXP(RES_2_PARALLEL(info->r10, info->r11) * info->c3);
1990   m_v_cap4       = 0;
1991   if (info->r4 != 0) m_has_r4 = 1;
1992   if (info->c4 != 0) m_has_c4 = 1;
1993   if (m_has_r4 && m_has_c4)
1994      m_exponent4    = RC_CHARGE_EXP(info->r4 * info->c4);
1995
1996   this->step();
1997}
1998
1999
2000/* the different logic and xtime states */
2001enum
2002{
2003   XTIME__IN0_0__IN1_0__IN0_NOX__IN1_NOX = 0,
2004   XTIME__IN0_0__IN1_0__IN0_NOX__IN1_X,
2005   XTIME__IN0_0__IN1_0__IN0_X__IN1_NOX,
2006   XTIME__IN0_0__IN1_0__IN0_X__IN1_X,
2007   XTIME__IN0_0__IN1_1__IN0_NOX__IN1_NOX,
2008   XTIME__IN0_0__IN1_1__IN0_NOX__IN1_X,
2009   XTIME__IN0_0__IN1_1__IN0_X__IN1_NOX,
2010   XTIME__IN0_0__IN1_1__IN0_X__IN1_X,
2011   XTIME__IN0_1__IN1_0__IN0_NOX__IN1_NOX,
2012   XTIME__IN0_1__IN1_0__IN0_NOX__IN1_X,
2013   XTIME__IN0_1__IN1_0__IN0_X__IN1_NOX,
2014   XTIME__IN0_1__IN1_0__IN0_X__IN1_X,
2015   XTIME__IN0_1__IN1_1__IN0_NOX__IN1_NOX,
2016   XTIME__IN0_1__IN1_1__IN0_NOX__IN1_X,
2017   XTIME__IN0_1__IN1_1__IN0_X__IN1_NOX,
2018   XTIME__IN0_1__IN1_1__IN0_X__IN1_X
2019};
2020
2021
2022/************************************************************************
2023 *
2024 * DST_XTIME_BUFFER - Buffer/Invertor gate implementation using X_TIME
2025 *
2026 * If OUT_LOW and OUT_HIGH are defined then the output will be energy.
2027 * If they are both 0, then the output will be X_TIME logic.
2028 *
2029 ************************************************************************/
2030#define DST_XTIME_BUFFER__IN            DISCRETE_INPUT(0)
2031#define DST_XTIME_BUFFER_OUT_LOW        DISCRETE_INPUT(1)
2032#define DST_XTIME_BUFFER_OUT_HIGH       DISCRETE_INPUT(2)
2033#define DST_XTIME_BUFFER_INVERT         DISCRETE_INPUT(3)
2034
2035DISCRETE_STEP(dst_xtime_buffer)
2036{
2037   int in0 = (int)DST_XTIME_BUFFER__IN;
2038   int out = in0;
2039   int out_is_energy = 1;
2040
2041   double x_time = DST_XTIME_BUFFER__IN - in0;
2042
2043   double out_low = DST_XTIME_BUFFER_OUT_LOW;
2044   double out_high = DST_XTIME_BUFFER_OUT_HIGH;
2045
2046   if (out_low ==0 && out_high == 0)
2047      out_is_energy = 0;
2048
2049   if (DST_XTIME_BUFFER_INVERT != 0)
2050      out ^= 1;
2051
2052   if (out_is_energy)
2053   {
2054      if (x_time > 0)
2055      {
2056         double diff = out_high - out_low;
2057         diff = out ? diff * x_time : diff * (1.0 - x_time);
2058         set_output(0,  out_low + diff);
2059      }
2060      else
2061         set_output(0,  out ? out_high : out_low);
2062   }
2063   else
2064      set_output(0,  out + x_time);
2065}
2066
2067
2068/************************************************************************
2069 *
2070 * DST_XTIME_AND - AND/NAND gate implementation using X_TIME
2071 *
2072 * If OUT_LOW and OUT_HIGH are defined then the output will be energy.
2073 * If they are both 0, then the output will be X_TIME logic.
2074 *
2075 ************************************************************************/
2076#define DST_XTIME_AND__IN0          DISCRETE_INPUT(0)
2077#define DST_XTIME_AND__IN1          DISCRETE_INPUT(1)
2078#define DST_XTIME_AND_OUT_LOW       DISCRETE_INPUT(2)
2079#define DST_XTIME_AND_OUT_HIGH      DISCRETE_INPUT(3)
2080#define DST_XTIME_AND_INVERT        DISCRETE_INPUT(4)
2081
2082DISCRETE_STEP(dst_xtime_and)
2083{
2084   int in0 = (int)DST_XTIME_AND__IN0;
2085   int in1 = (int)DST_XTIME_AND__IN1;
2086   int out = 0;
2087   int out_is_energy = 1;
2088
2089   double x_time = 0;
2090   double x_time0 = DST_XTIME_AND__IN0 - in0;
2091   double x_time1 = DST_XTIME_AND__IN1 - in1;
2092
2093   int in0_has_xtime = x_time0 > 0 ? 1 : 0;
2094   int in1_has_xtime = x_time1 > 0 ? 1 : 0;
2095
2096   double out_low = DST_XTIME_AND_OUT_LOW;
2097   double out_high = DST_XTIME_AND_OUT_HIGH;
2098
2099   if (out_low ==0 && out_high == 0)
2100      out_is_energy = 0;
2101
2102   switch ((in0 << 3) | (in1 << 2) | (in0_has_xtime < 1) | in1_has_xtime)
2103   {
2104      // these are all 0
2105      //case XTIME__IN0_0__IN1_0__IN0_NOX__IN1_NOX:
2106      //case XTIME__IN0_0__IN1_1__IN0_NOX__IN1_NOX:
2107      //case XTIME__IN0_1__IN1_0__IN0_NOX__IN1_NOX:
2108      //case XTIME__IN0_0__IN1_0__IN0_NOX__IN1_X:
2109      //case XTIME__IN0_0__IN1_0__IN0_X__IN1_NOX:
2110      //case XTIME__IN0_0__IN1_1__IN0_NOX__IN1_X:
2111      //case XTIME__IN0_1__IN1_0__IN0_X__IN1_NOX:
2112      //  break;
2113
2114      case XTIME__IN0_1__IN1_1__IN0_NOX__IN1_NOX:
2115         out = 1;
2116         break;
2117
2118      case XTIME__IN0_0__IN1_1__IN0_X__IN1_NOX:
2119         /*
2120          * in0  1   ------
2121          *      0         -------
2122          *          ...^....^...
2123          *
2124          * in1  1   -------------
2125          *      0
2126          *          ...^....^...
2127          *
2128          * out  1   ------
2129          *      0         ------
2130          *          ...^....^...
2131          */
2132         x_time = x_time0;
2133         break;
2134
2135      case XTIME__IN0_1__IN1_0__IN0_NOX__IN1_X:
2136         /*
2137          * in0  1   -------------
2138          *      0
2139          *          ...^....^...
2140          *
2141          * in1  1   ------
2142          *      0         -------
2143          *          ...^....^...
2144          *
2145          * out  1   ------
2146          *      0         ------
2147          *          ...^....^...
2148          */
2149         x_time = x_time1;
2150         break;
2151
2152      case XTIME__IN0_0__IN1_0__IN0_X__IN1_X:
2153         /*
2154          * in0  1   -----              -------
2155          *      0        --------             ------
2156          *          ...^....^...       ...^....^...
2157          *
2158          * in1  1   -------            -----
2159          *      0          ------           --------
2160          *          ...^....^...       ...^....^...
2161          *
2162          * out  1   -----              -----
2163          *      0        -------            -------
2164          *          ...^....^...       ...^....^...
2165          */
2166         // use x_time of input that went to 0 first/longer
2167         if (x_time0 >= x_time1)
2168            x_time = x_time0;
2169         else
2170            x_time = x_time1;
2171         break;
2172
2173      case XTIME__IN0_0__IN1_1__IN0_X__IN1_X:
2174         /*
2175          * in0  1   -------           -----
2176          *      0          -----           -------
2177          *          ...^....^...      ...^....^...
2178          *
2179          * in1  1        -------             -----
2180          *      0   -----             -------
2181          *          ...^....^...      ...^....^...
2182          *
2183          * out  1        --
2184          *      0   -----  -----      ------------
2185          *          ...^....^...      ...^....^...
2186          */
2187         // may have went high for a bit in this cycle
2188         //if (x_time0 < x_time1)
2189         //  x_time = time1 - x_time0;
2190         break;
2191
2192      case XTIME__IN0_1__IN1_0__IN0_X__IN1_X:
2193         /*
2194          * in0  1        -------             -----
2195          *      0   -----             -------
2196          *          ...^....^...      ...^....^...
2197          *
2198          * in1  1   -------           -----
2199          *      0          -----           -------
2200          *          ...^....^...      ...^....^...
2201          *
2202          * out  1        --
2203          *      0   -----  -----      ------------
2204          *          ...^....^...      ...^....^...
2205          */
2206         // may have went high for a bit in this cycle
2207         //if (x_time0 > x_time1)
2208         //  x_time = x_time0 - x_time1;
2209         break;
2210
2211      case XTIME__IN0_1__IN1_1__IN0_NOX__IN1_X:
2212         /*
2213          * in0  1   ------------
2214          *      0
2215          *          ...^....^...
2216          *
2217          * in1  1         ------
2218          *      0   ------
2219          *          ...^....^...
2220          *
2221          * out  1         ------
2222          *      0   ------
2223          *          ...^....^...
2224          */
2225         out = 1;
2226         x_time = x_time1;
2227         break;
2228
2229      case XTIME__IN0_1__IN1_1__IN0_X__IN1_NOX:
2230         /*
2231          * in1  0         ------
2232          *      0   ------
2233          *          ...^....^...
2234          *
2235          * in1  1   ------------
2236          *      0
2237          *          ...^....^...
2238          *
2239          * out  1         ------
2240          *      0   ------
2241          *          ...^....^...
2242          */
2243         out = 1;
2244         x_time = x_time0;
2245         break;
2246
2247      case XTIME__IN0_1__IN1_1__IN0_X__IN1_X:
2248         /*
2249          * in0  1         ------          --------
2250          *      0   ------            ----
2251          *          ...^....^...      ...^....^...
2252          *
2253          * in1  1       --------            ------
2254          *      0   ----              ------
2255          *          ...^....^...      ...^....^...
2256          *
2257          * out  1         ------            ------
2258          *      0   ------            ------
2259          *          ...^....^...      ...^....^...
2260          */
2261         out = 1;
2262         if (x_time0 < x_time1)
2263            x_time = x_time0;
2264         else
2265            x_time = x_time1;
2266         break;
2267   }
2268
2269   if (DST_XTIME_AND_INVERT != 0)
2270      out ^= 1;
2271
2272   if (out_is_energy)
2273   {
2274      if (x_time > 0)
2275      {
2276         double diff = out_high - out_low;
2277         diff = out ? diff * x_time : diff * (1.0 - x_time);
2278         set_output(0,  out_low + diff);
2279      }
2280      else
2281         set_output(0,  out ? out_high : out_low);
2282   }
2283   else
2284      set_output(0,  out + x_time);
2285}
2286
2287
2288/************************************************************************
2289 *
2290 * DST_XTIME_OR - OR/NOR gate implementation using X_TIME
2291 *
2292 * If OUT_LOW and OUT_HIGH are defined then the output will be energy.
2293 * If they are both 0, then the output will be X_TIME logic.
2294 *
2295 ************************************************************************/
2296#define DST_XTIME_OR__IN0           DISCRETE_INPUT(0)
2297#define DST_XTIME_OR__IN1           DISCRETE_INPUT(1)
2298#define DST_XTIME_OR_OUT_LOW        DISCRETE_INPUT(2)
2299#define DST_XTIME_OR_OUT_HIGH       DISCRETE_INPUT(3)
2300#define DST_XTIME_OR_INVERT         DISCRETE_INPUT(4)
2301
2302DISCRETE_STEP(dst_xtime_or)
2303{
2304   int in0 = (int)DST_XTIME_OR__IN0;
2305   int in1 = (int)DST_XTIME_OR__IN1;
2306   int out = 1;
2307   int out_is_energy = 1;
2308
2309   double x_time = 0;
2310   double x_time0 = DST_XTIME_OR__IN0 - in0;
2311   double x_time1 = DST_XTIME_OR__IN1 - in1;
2312
2313   int in0_has_xtime = x_time0 > 0 ? 1 : 0;
2314   int in1_has_xtime = x_time1 > 0 ? 1 : 0;
2315
2316   double out_low = DST_XTIME_OR_OUT_LOW;
2317   double out_high = DST_XTIME_OR_OUT_HIGH;
2318
2319   if (out_low ==0 && out_high == 0)
2320      out_is_energy = 0;
2321
2322   switch ((in0 << 3) | (in1 << 2) | (in0_has_xtime < 1) | in1_has_xtime)
2323   {
2324      // these are all 1
2325      //case XTIME__IN0_1__IN1_1__IN0_NOX__IN1_NOX:
2326      //case XTIME__IN0_0__IN1_1__IN0_NOX__IN1_NOX:
2327      //case XTIME__IN0_1__IN1_0__IN0_NOX__IN1_NOX:
2328      //case XTIME__IN0_1__IN1_0__IN0_NOX__IN1_X:
2329      //case XTIME__IN0_0__IN1_1__IN0_X__IN1_NOX:
2330      //case XTIME__IN0_1__IN1_1__IN0_NOX__IN1_X:
2331      //case XTIME__IN0_1__IN1_1__IN0_X__IN1_NOX:
2332      //  break;
2333
2334      case XTIME__IN0_0__IN1_0__IN0_NOX__IN1_NOX:
2335         out = 0;
2336         break;
2337
2338      case XTIME__IN0_0__IN1_0__IN0_NOX__IN1_X:
2339         /*
2340          * in0  1
2341          *      0   -------------
2342          *          ...^....^...
2343          *
2344          * in1  1   ------
2345          *      0         -------
2346          *          ...^....^...
2347          *
2348          * out  1   ------
2349          *      0         ------
2350          *          ...^....^...
2351          */
2352         out = 0;
2353         x_time = x_time1;
2354         break;
2355
2356      case XTIME__IN0_0__IN1_0__IN0_X__IN1_NOX:
2357         /*
2358          * in0  1   ------
2359          *      0         -------
2360          *          ...^....^...
2361          *
2362          * in1  1
2363          *      0   -------------
2364          *          ...^....^...
2365          *
2366          * out  1   ------
2367          *      0         ------
2368          *          ...^....^...
2369          */
2370         out = 0;
2371         x_time = x_time0;
2372         break;
2373
2374      case XTIME__IN0_0__IN1_0__IN0_X__IN1_X:
2375         /*
2376          * in0  1   -----              -------
2377          *      0        --------             ------
2378          *          ...^....^...       ...^....^...
2379          *
2380          * in1  1   -------            -----
2381          *      0          ------           --------
2382          *          ...^....^...       ...^....^...
2383          *
2384          * out  1   -------            -------
2385          *      0          -----              -----
2386          *          ...^....^...       ...^....^...
2387          */
2388         out = 0;
2389         // use x_time of input that was 1 last/longer
2390         // this means at 0 for less x_time
2391         if (x_time0 > x_time1)
2392            x_time = x_time1;
2393         else
2394            x_time = x_time0;
2395         break;
2396
2397      case XTIME__IN0_0__IN1_1__IN0_NOX__IN1_X:
2398         /*
2399          * in0  1
2400          *      0   ------------
2401          *          ...^....^...
2402          *
2403          * in1  1         ------
2404          *      0   ------
2405          *          ...^....^...
2406          *
2407          * out  1         ------
2408          *      0   ------
2409          *          ...^....^...
2410          */
2411         x_time = x_time1;
2412         break;
2413
2414      case XTIME__IN0_1__IN1_0__IN0_X__IN1_NOX:
2415         /*
2416          * in0  1         ------
2417          *      0   ------
2418          *          ...^....^...
2419          *
2420          * in1  1
2421          *      0   ------------
2422          *          ...^....^...
2423          *
2424          * out  1         ------
2425          *      0   ------
2426          *          ...^....^...
2427          */
2428         x_time = x_time0;
2429         break;
2430
2431      case XTIME__IN0_0__IN1_1__IN0_X__IN1_X:
2432         /*
2433          * in0  1   -------           -----
2434          *      0          -----           -------
2435          *          ...^....^...      ...^....^...
2436          *
2437          * in1  1        -------             -----
2438          *      0   -----             -------
2439          *          ...^....^...      ...^....^...
2440          *
2441          * out  1   ------------      -----  -----
2442          *      0                          --
2443          *          ...^....^...      ...^....^...
2444          */
2445         // if (x_time0 > x_time1)
2446            /* Not sure if it is better to use 1
2447             * or the total energy which would smear the switch points together.
2448             * Let's try just using 1 */
2449            //x_time = xtime_0 - xtime_1;
2450         break;
2451
2452      case XTIME__IN0_1__IN1_0__IN0_X__IN1_X:
2453         /*
2454          * in0  1        -------             -----
2455          *      0   -----             -------
2456          *          ...^....^...      ...^....^...
2457          *
2458          * in1  1   -------           -----
2459          *      0          -----           -------
2460          *          ...^....^...      ...^....^...
2461          *
2462          * out  1   ------------      -----  -----
2463          *      0                          --
2464          *          ...^....^...      ...^....^...
2465          */
2466         //if (x_time0 < x_time1)
2467            /* Not sure if it is better to use 1
2468             * or the total energy which would smear the switch points together.
2469             * Let's try just using 1 */
2470            //x_time = xtime_1 - xtime_0;
2471         break;
2472
2473      case XTIME__IN0_1__IN1_1__IN0_X__IN1_X:
2474         /*
2475          * in0  1         ------          --------
2476          *      0   ------            ----
2477          *          ...^....^...      ...^....^...
2478          *
2479          * in1  1       --------            ------
2480          *      0   ----              ------
2481          *          ...^....^...      ...^....^...
2482          *
2483          * out  1       --------          --------
2484          *      0   ----              ----
2485          *          ...^....^...      ...^....^...
2486          */
2487         if (x_time0 > x_time1)
2488            x_time = x_time0;
2489         else
2490            x_time = x_time1;
2491         break;
2492   }
2493
2494   if (DST_XTIME_OR_INVERT != 0)
2495      out ^= 1;
2496
2497   if (out_is_energy)
2498   {
2499      if (x_time > 0)
2500      {
2501         double diff = out_high - out_low;
2502         diff = out ? diff * x_time : diff * (1.0 - x_time);
2503         set_output(0,  out_low + diff);
2504      }
2505      else
2506         set_output(0,  out ? out_high : out_low);
2507   }
2508   else
2509      set_output(0,  out + x_time);
2510}
2511
2512
2513/************************************************************************
2514 *
2515 * DST_XTIME_XOR - XOR/XNOR gate implementation using X_TIME
2516 *
2517 * If OUT_LOW and OUT_HIGH are defined then the output will be energy.
2518 * If they are both 0, then the output will be X_TIME logic.
2519 *
2520 ************************************************************************/
2521#define DST_XTIME_XOR__IN0          DISCRETE_INPUT(0)
2522#define DST_XTIME_XOR__IN1          DISCRETE_INPUT(1)
2523#define DST_XTIME_XOR_OUT_LOW       DISCRETE_INPUT(2)
2524#define DST_XTIME_XOR_OUT_HIGH      DISCRETE_INPUT(3)
2525#define DST_XTIME_XOR_INVERT        DISCRETE_INPUT(4)
2526
2527DISCRETE_STEP(dst_xtime_xor)
2528{
2529   int in0 = (int)DST_XTIME_XOR__IN0;
2530   int in1 = (int)DST_XTIME_XOR__IN1;
2531   int out = 1;
2532   int out_is_energy = 1;
2533
2534   double x_time = 0;
2535   double x_time0 = DST_XTIME_XOR__IN0 - in0;
2536   double x_time1 = DST_XTIME_XOR__IN1 - in1;
2537
2538   int in0_has_xtime = x_time0 > 0 ? 1 : 0;
2539   int in1_has_xtime = x_time1 > 0 ? 1 : 0;
2540
2541   double out_low = DST_XTIME_XOR_OUT_LOW;
2542   double out_high = DST_XTIME_XOR_OUT_HIGH;
2543
2544   if (out_low ==0 && out_high == 0)
2545      out_is_energy = 0;
2546
2547   switch ((in0 << 3) | (in1 << 2) | (in0_has_xtime < 1) | in1_has_xtime)
2548   {
2549      // these are all 1
2550      //case XTIME__IN0_0__IN1_1__IN0_NOX__IN1_NOX:
2551      //case XTIME__IN0_1__IN1_0__IN0_NOX__IN1_NOX:
2552      //  break;
2553
2554      case XTIME__IN0_1__IN1_1__IN0_NOX__IN1_NOX:
2555      case XTIME__IN0_0__IN1_0__IN0_NOX__IN1_NOX:
2556         out = 0;
2557         break;
2558
2559      case XTIME__IN0_1__IN1_0__IN0_X__IN1_NOX:
2560         /*
2561          * in0  1         ------
2562          *      0   ------
2563          *          ...^....^...
2564          *
2565          * in1  1
2566          *      0   ------------
2567          *          ...^....^...
2568          *
2569          * out  1         ------
2570          *      0   ------
2571          *          ...^....^...
2572          */
2573      case XTIME__IN0_0__IN1_1__IN0_X__IN1_NOX:
2574         /*
2575          * in0  1   ------
2576          *      0         -------
2577          *          ...^....^...
2578          *
2579          * in1  1   -------------
2580          *      0
2581          *          ...^....^...
2582          *
2583          * out  1         ------
2584          *      0   ------
2585          *          ...^....^...
2586          */
2587         x_time = x_time0;
2588         break;
2589
2590      case XTIME__IN0_0__IN1_1__IN0_NOX__IN1_X:
2591         /*
2592          * in0  1
2593          *      0   ------------
2594          *          ...^....^...
2595          *
2596          * in1  1         ------
2597          *      0   ------
2598          *          ...^....^...
2599          *
2600          * out  1         ------
2601          *      0   ------
2602          *          ...^....^...
2603          */
2604      case XTIME__IN0_1__IN1_0__IN0_NOX__IN1_X:
2605         /*
2606          * in0  1   -------------
2607          *      0
2608          *          ...^....^...
2609          *
2610          * in1  1   ------
2611          *      0         -------
2612          *          ...^....^...
2613          *
2614          * out  1         ------
2615          *      0   ------
2616          *          ...^....^...
2617          */
2618         x_time = x_time1;
2619         break;
2620
2621      case XTIME__IN0_0__IN1_0__IN0_X__IN1_NOX:
2622         /*
2623          * in0  1   ------
2624          *      0         ------
2625          *          ...^....^...
2626          *
2627          * in1  1
2628          *      0   ------------
2629          *          ...^....^...
2630          *
2631          * out  1   ------
2632          *      0         ------
2633          *          ...^....^...
2634          */
2635      case XTIME__IN0_1__IN1_1__IN0_X__IN1_NOX:
2636         /*
2637          * in1  0         ------
2638          *      0   ------
2639          *          ...^....^...
2640          *
2641          * in1  1   ------------
2642          *      0
2643          *          ...^....^...
2644          *
2645          * out  1   ------
2646          *      0         ------
2647          *          ...^....^...
2648          */
2649         out = 0;
2650         x_time = x_time0;
2651         break;
2652
2653      case XTIME__IN0_0__IN1_0__IN0_NOX__IN1_X:
2654         /*
2655          * in0  1
2656          *      0   ------------
2657          *          ...^....^...
2658          *
2659          * in1  1   ------
2660          *      0         ------
2661          *          ...^....^...
2662          *
2663          * out  1   ------
2664          *      0         ------
2665          *          ...^....^...
2666          */
2667      case XTIME__IN0_1__IN1_1__IN0_NOX__IN1_X:
2668         /*
2669          * in0  1   ------------
2670          *      0
2671          *          ...^....^...
2672          *
2673          * in1  1         ------
2674          *      0   ------
2675          *          ...^....^...
2676          *
2677          * out  1   ------
2678          *      0         ------
2679          *          ...^....^...
2680          */
2681         out = 0;
2682         x_time = x_time1;
2683         break;
2684
2685      case XTIME__IN0_0__IN1_0__IN0_X__IN1_X:
2686         /*
2687          * in0  1   -----              -------
2688          *      0        -------              -----
2689          *          ...^....^...       ...^....^...
2690          *
2691          * in1  1   -------            -----
2692          *      0          -----            -------
2693          *          ...^....^...       ...^....^...
2694          *
2695          * out  1        --                 --
2696          *      0   -----  -----       -----  -----
2697          *          ...^....^...       ...^....^...
2698          */
2699      case XTIME__IN0_1__IN1_1__IN0_X__IN1_X:
2700         /*
2701          * in0  1         ------          --------
2702          *      0   ------            ----
2703          *          ...^....^...      ...^....^...
2704          *
2705          * in1  1       --------            ------
2706          *      0   ----              ------
2707          *          ...^....^...      ...^....^...
2708          *
2709          * out  1       --                --
2710          *      0   ----  ------      ----  ------
2711          *          ...^....^...      ...^....^...
2712          */
2713         out = 0;
2714         /* Not sure if it is better to use 0
2715          * or the total energy which would smear the switch points together.
2716          * Let's try just using 0 */
2717         // x_time = abs(x_time0 - x_time1);
2718         break;
2719
2720      case XTIME__IN0_0__IN1_1__IN0_X__IN1_X:
2721         /*
2722          * in0  1   -------           -----
2723          *      0          -----           -------
2724          *          ...^....^...      ...^....^...
2725          *
2726          * in1  1        -------             -----
2727          *      0   -----             -------
2728          *          ...^....^...      ...^....^...
2729          *
2730          * out  1   -----  -----      -----  -----
2731          *      0        --                --
2732          *          ...^....^...      ...^....^...
2733          */
2734      case XTIME__IN0_1__IN1_0__IN0_X__IN1_X:
2735         /*
2736          * in0  1        -------             -----
2737          *      0   -----             -------
2738          *          ...^....^...      ...^....^...
2739          *
2740          * in1  1   -------           -----
2741          *      0          -----           -------
2742          *          ...^....^...      ...^....^...
2743          *
2744          * out  1   -----  -----      -----  -----
2745          *      0        --                --
2746          *          ...^....^...      ...^....^...
2747          */
2748         /* Not sure if it is better to use 1
2749          * or the total energy which would smear the switch points together.
2750          * Let's try just using 1 */
2751         // x_time = 1.0 - abs(x_time0 - x_time1);
2752         break;
2753}
2754
2755   if (DST_XTIME_XOR_INVERT != 0)
2756      out ^= 1;
2757
2758   if (out_is_energy)
2759   {
2760      if (x_time > 0)
2761      {
2762         double diff = out_high - out_low;
2763         diff = out ? diff * x_time : diff * (1.0 - x_time);
2764         set_output(0,  out_low + diff);
2765      }
2766      else
2767         set_output(0,  out ? out_high : out_low);
2768   }
2769   else
2770      set_output(0,  out + x_time);
2771}
Property changes on: trunk/src/emu/sound/disc_mth.inc
Added: svn:mime-type
   + text/plain
Added: svn:eol-style
   + native
trunk/src/emu/sound/disc_cls.h
r28731r28732
101101
102102/*************************************
103103 *
104 *  disc_sys.c
104 *  disc_sys.inc
105105 *
106106 *************************************/
107107
r28731r28732
137137
138138/*************************************
139139 *
140 *  disc_inp.c
140 *  disc_inp.inc
141141 *
142142 *************************************/
143143
trunk/src/emu/sound/discrete.c
r28731r28732
153153 *
154154 *************************************/
155155
156#include "disc_sys.c"       /* discrete core modules and support functions */
157#include "disc_wav.c"       /* Wave sources   - SINE/SQUARE/NOISE/etc */
158#include "disc_mth.c"       /* Math Devices   - ADD/GAIN/etc */
159#include "disc_inp.c"       /* Input Devices  - INPUT/CONST/etc */
160#include "disc_flt.c"       /* Filter Devices - RCF/HPF/LPF */
161#include "disc_dev.c"       /* Popular Devices - NE555/etc */
156#include "disc_sys.inc"       /* discrete core modules and support functions */
157#include "disc_wav.inc"       /* Wave sources   - SINE/SQUARE/NOISE/etc */
158#include "disc_mth.inc"       /* Math Devices   - ADD/GAIN/etc */
159#include "disc_inp.inc"       /* Input Devices  - INPUT/CONST/etc */
160#include "disc_flt.inc"       /* Filter Devices - RCF/HPF/LPF */
161#include "disc_dev.inc"       /* Popular Devices - NE555/etc */
162162
163163/*************************************
164164 *
trunk/src/emu/sound/discrete.h
r28731r28732
337337 *
338338 ***********************************************************************
339339 =======================================================================
340 * from from disc_inp.c
340 * from from disc_inp.inc
341341 =======================================================================
342342 ***********************************************************************
343343 *
r28731r28732
451451 *
452452 ***********************************************************************
453453 =======================================================================
454 * from from disc_wav.c
454 * from from disc_wav.inc
455455 * Generic modules
456456 =======================================================================
457457 ***********************************************************************
r28731r28732
797797 *
798798 ***********************************************************************
799799 =======================================================================
800 * from from disc_wav.c
800 * from from disc_wav.inc
801801 * Component specific modules
802802 =======================================================================
803803 ***********************************************************************
r28731r28732
11651165 *
11661166 ***********************************************************************
11671167 =======================================================================
1168 * from from disc_wav.c
1168 * from from disc_wav.inc
11691169 * Not yet implemented
11701170 =======================================================================
11711171 ***********************************************************************
r28731r28732
11971197 *
11981198 ***********************************************************************
11991199 =======================================================================
1200 * from from disc_mth.c
1200 * from from disc_mth.inc
12011201 * Generic modules
12021202 =======================================================================
12031203 ***********************************************************************
r28731r28732
17981798 *
17991799 ***********************************************************************
18001800 =======================================================================
1801 * from from disc_mth.c
1801 * from from disc_mth.inc
18021802 * Component specific modules
18031803 =======================================================================
18041804 ***********************************************************************
r28731r28732
22142214 *
22152215 ***********************************************************************
22162216 =======================================================================
2217 * from from disc_flt.c
2217 * from from disc_flt.inc
22182218 * Generic modules
22192219 =======================================================================
22202220 ***********************************************************************
r28731r28732
22542254 *
22552255 ***********************************************************************
22562256 =======================================================================
2257 * from from disc_flt.c
2257 * from from disc_flt.inc
22582258 * Component specific modules
22592259 =======================================================================
22602260 ***********************************************************************
r28731r28732
29462946 *
29472947 ***********************************************************************
29482948 =======================================================================
2949 * from from disc_dev.c
2949 * from from disc_dev.inc
29502950 * Component specific modules
29512951 =======================================================================
29522952 ***********************************************************************
r28731r28732
45454545
45464546/*      Module Name                                                       out,  enum value,      #in,   {variable inputs},              {static inputs},    data pointer,   "name" */
45474547
4548/* from disc_inp.c */
4548/* from disc_inp.inc */
45494549#define DISCRETE_ADJUSTMENT(NODE,MIN,MAX,LOGLIN,TAG)                    DSC_SND_ENTRY( NODE, dss_adjustment  , DSS_NODE        , 6, DSE( NODE_NC,NODE_NC,NODE_NC,NODE_NC,NODE_NC,NODE_NC ), DSE( MIN,MAX,LOGLIN,0   ,0   ,100  ), TAG   , "DISCRETE_ADJUSTMENT" ),
45504550#define DISCRETE_ADJUSTMENTX(NODE,MIN,MAX,LOGLIN,TAG,PMIN,PMAX)         DSC_SND_ENTRY( NODE, dss_adjustment  , DSS_NODE        , 6, DSE( NODE_NC,NODE_NC,NODE_NC,NODE_NC,NODE_NC,NODE_NC ), DSE( MIN,MAX,LOGLIN,0   ,PMIN,PMAX ), TAG   , "DISCRETE_ADJUSTMENTX"  ),
45514551#define DISCRETE_CONSTANT(NODE,CONST)                                   DSC_SND_ENTRY( NODE, dss_constant    , DSS_NODE        , 1, DSE( NODE_NC ), DSE( CONST ) ,NULL  ,"DISCRETE_CONSTANT" ),
r28731r28732
45624562
45634563#define DISCRETE_INPUT_BUFFER(NODE, NUM)                                DSC_SND_ENTRY( NODE, dss_input_buffer, DSS_NODE        , 3, DSE( NUM,NODE_NC,NODE_NC ), DSE( NUM,1,0 ), NULL, "DISCRETE_INPUT_BUFFER" ),
45644564
4565/* from disc_wav.c */
4565/* from disc_wav.inc */
45664566/* generic modules */
45674567#define DISCRETE_COUNTER(NODE,ENAB,RESET,CLK,MIN,MAX,DIR,INIT0,CLKTYPE) DSC_SND_ENTRY( NODE, dss_counter     , DSS_NODE        , 8, DSE( ENAB,RESET,CLK,NODE_NC,NODE_NC,DIR,INIT0,NODE_NC ), DSE( ENAB,RESET,CLK,MIN,MAX,DIR,INIT0,CLKTYPE ), NULL, "DISCRETE_COUNTER" ),
45684568#define DISCRETE_COUNTER_7492(NODE,ENAB,RESET,CLK,CLKTYPE)              DSC_SND_ENTRY( NODE, dss_counter     , DSS_NODE        , 8, DSE( ENAB,RESET,CLK,NODE_NC,NODE_NC,NODE_NC,NODE_NC,NODE_NC ), DSE( ENAB,RESET,CLK,CLKTYPE,0,1,0,DISC_COUNTER_IS_7492 ), NULL, "DISCRETE_COUNTER_7492" ),
r28731r28732
45844584/* Not yet implemented */
45854585#define DISCRETE_ADSR_ENV(NODE,ENAB,TRIGGER,GAIN,ADSRTB)                DSC_SND_ENTRY( NODE, dss_adsr        , DSS_NODE        , 3, DSE( ENAB,TRIGGER,GAIN ), DSE( ENAB,TRIGGER,GAIN ), ADSRTB, "DISCRETE_ADSR_ENV" ),
45864586
4587/* from disc_mth.c */
4587/* from disc_mth.inc */
45884588/* generic modules */
45894589#define DISCRETE_ADDER2(NODE,ENAB,INP0,INP1)                            DSC_SND_ENTRY( NODE, dst_adder       , DSS_NODE        , 3, DSE( ENAB,INP0,INP1 ), DSE( ENAB,INP0,INP1 ), NULL, "DISCRETE_ADDER2" ),
45904590#define DISCRETE_ADDER3(NODE,ENAB,INP0,INP1,INP2)                       DSC_SND_ENTRY( NODE, dst_adder       , DSS_NODE        , 4, DSE( ENAB,INP0,INP1,INP2 ), DSE( ENAB,INP0,INP1,INP2 ), NULL, "DISCRETE_ADDER3" ),
r28731r28732
46594659#define DISCRETE_XTIME_XOR(NODE,IN0,IN1,LOW,HIGH)                       DSC_SND_ENTRY( NODE, dst_xtime_xor   , DSS_NODE        , 5, DSE( IN0,IN1,LOW,HIGH,NODE_NC ), DSE( IN0,IN1,LOW,HIGH,0 ), NULL, "DISCRETE_XTIME_XOR" ),
46604660#define DISCRETE_XTIME_XNOR(NODE,IN0,IN1,LOW,HIGH)                      DSC_SND_ENTRY( NODE, dst_xtime_xnor  , DSS_NODE        , 5, DSE( IN0,IN1,LOW,HIGH,NODE_NC ), DSE( IN0,IN1,LOW,HIGH,1 ), NULL, "DISCRETE_XTIME_XNOR" ),
46614661
4662/* from disc_flt.c */
4662/* from disc_flt.inc */
46634663/* generic modules */
46644664#define DISCRETE_FILTER1(NODE,ENAB,INP0,FREQ,TYPE)                      DSC_SND_ENTRY( NODE, dst_filter1     , DSS_NODE        , 4, DSE( ENAB,INP0,NODE_NC,NODE_NC ), DSE( ENAB,INP0,FREQ,TYPE ), NULL, "DISCRETE_FILTER1" ),
46654665#define DISCRETE_FILTER2(NODE,ENAB,INP0,FREQ,DAMP,TYPE)                 DSC_SND_ENTRY( NODE, dst_filter2     , DSS_NODE        , 5, DSE( ENAB,INP0,NODE_NC,NODE_NC,NODE_NC ), DSE( ENAB,INP0,FREQ,DAMP,TYPE ), NULL, "DISCRETE_FILTER2" ),
r28731r28732
46844684#define DISCRETE_RCDISC2N(NODE,SWITCH,INP0,RVAL0,INP1,RVAL1,CVAL)       DSC_SND_ENTRY( NODE, dst_rcdisc2n    , DSS_NODE        , 6, DSE( SWITCH,INP0,NODE_NC,INP1,NODE_NC,NODE_NC ), DSE( SWITCH,INP0,RVAL0,INP1,RVAL1,CVAL ), NULL, "DISCRETE_RCDISC2N" ),
46854685#define DISCRETE_RCFILTERN(NODE,ENAB,INP0,RVAL,CVAL)                    DSC_SND_ENTRY( NODE, dst_rcfiltern   , DSS_NODE        , 4, DSE( ENAB,INP0,NODE_NC,NODE_NC ), DSE( ENAB,INP0,RVAL,CVAL ), NULL, "DISCRETE_RCFILTERN" ),
46864686
4687/* from disc_dev.c */
4687/* from disc_dev.inc */
46884688/* generic modules */
46894689#define DISCRETE_CUSTOM1(NODE,CLASS,IN0,INFO)                                 DSC_SND_ENTRY( NODE, CLASS, DST_CUSTOM      , 1, DSE( IN0 ), DSE( IN0 ), INFO, "DISCRETE_CUSTOM1" ),
46904690#define DISCRETE_CUSTOM2(NODE,CLASS,IN0,IN1,INFO)                             DSC_SND_ENTRY( NODE, CLASS, DST_CUSTOM      , 2, DSE( IN0,IN1 ), DSE( IN0,IN1 ), INFO, "DISCRETE_CUSTOM2" ),
trunk/src/emu/sound/disc_wav.inc
r0r28732
1/************************************************************************
2 *
3 *  MAME - Discrete sound system emulation library
4 *  Written by Keith Wilkins (mame@esplexo.co.uk)
5 *
6 *  (c) K.Wilkins 2000
7 *
8 ************************************************************************
9 *
10 * DSS_COUNTER        - External clock Binary Counter
11 * DSS_LFSR_NOISE     - Linear Feedback Shift Register Noise
12 * DSS_NOISE          - Noise Source - Random source
13 * DSS_NOTE           - Note/tone generator
14 * DSS_OP_AMP_OSC     - Op Amp oscillator circuits
15 * DSS_SAWTOOTHWAVE   - Sawtooth waveform generator
16 * DSS_SCHMITT_OSC    - Schmitt Feedback Oscillator
17 * DSS_SINEWAVE       - Sinewave generator source code
18 * DSS_SQUAREWAVE     - Squarewave generator source code
19 * DSS_SQUAREWFIX     - Squarewave generator - fixed frequency
20 * DSS_SQUAREWAVE2    - Squarewave generator - by t_on/t_off
21 * DSS_TRIANGLEWAVE   - Triangle waveform generator
22 *
23 ************************************************************************/
24
25
26
27
28
29
30
31/************************************************************************
32 *
33 * DSS_COUNTER - External clock Binary Counter
34 *
35 * input0    - Enable input value
36 * input1    - Reset input (active high)
37 * input2    - Clock Input
38 * input3    - Max count
39 * input4    - Direction - 0=down, 1=up
40 * input5    - Reset Value
41 * input6    - Clock type
42 *
43 * Jan 2004, D Renaud.
44 ************************************************************************/
45#define DSS_COUNTER__ENABLE     DISCRETE_INPUT(0)
46#define DSS_COUNTER__RESET      DISCRETE_INPUT(1)
47#define DSS_COUNTER__CLOCK      DISCRETE_INPUT(2)
48#define DSS_COUNTER__MIN        DISCRETE_INPUT(3)
49#define DSS_COUNTER__MAX        DISCRETE_INPUT(4)
50#define DSS_COUNTER__DIR        DISCRETE_INPUT(5)
51#define DSS_COUNTER__INIT       DISCRETE_INPUT(6)
52#define DSS_COUNTER__CLOCK_TYPE DISCRETE_INPUT(7)
53#define DSS_7492__CLOCK_TYPE     DSS_COUNTER__MIN
54
55static const int disc_7492_count[6] = {0x00, 0x01, 0x02, 0x04, 0x05, 0x06};
56
57DISCRETE_STEP(dss_counter)
58{
59   double  cycles;
60   double  ds_clock;
61   int     clock = 0, inc = 0;
62   UINT32  last_count = m_last_count;  /* it is different then output in 7492 */
63   double  x_time = 0;
64   UINT32  count = last_count;
65
66   ds_clock = DSS_COUNTER__CLOCK;
67   if (UNEXPECTED(m_clock_type == DISC_CLK_IS_FREQ))
68   {
69      /* We need to keep clocking the internal clock even if disabled. */
70      cycles = (m_t_left + this->sample_time()) * ds_clock;
71      inc    = (int)cycles;
72      m_t_left = (cycles - inc) / ds_clock;
73      if (inc) x_time = m_t_left / this->sample_time();
74   }
75   else
76   {
77      clock  = (int)ds_clock;
78      /* x_time from input clock */
79      x_time = ds_clock - clock;
80   }
81
82
83   /* If reset enabled then set output to the reset value.  No x_time in reset. */
84   if (UNEXPECTED(DSS_COUNTER__RESET))
85   {
86      m_last_count = (int)DSS_COUNTER__INIT;
87      set_output(0, (int)DSS_COUNTER__INIT);
88      return;
89   }
90
91   /*
92    * Only count if module is enabled.
93    * This has the effect of holding the output at it's current value.
94    */
95   if (EXPECTED(DSS_COUNTER__ENABLE))
96   {
97      double v_out;
98
99      switch (m_clock_type)
100      {
101         case DISC_CLK_ON_F_EDGE:
102         case DISC_CLK_ON_R_EDGE:
103            /* See if the clock has toggled to the proper edge */
104            clock = (clock != 0);
105            if (m_last_clock != clock)
106            {
107               m_last_clock = clock;
108               if (m_clock_type == clock)
109               {
110                  /* Toggled */
111                  inc = 1;
112               }
113            }
114            break;
115
116         case DISC_CLK_BY_COUNT:
117            /* Clock number of times specified. */
118            inc = clock;
119            break;
120      }
121
122      /* use loops because init is not always min or max */
123      if (DSS_COUNTER__DIR)
124      {
125         count += inc;
126         while (count > m_max)
127         {
128            count -= m_diff;
129         }
130      }
131      else
132      {
133         count -= inc;
134         while (count < m_min || count > (0xffffffff - inc))
135         {
136            count += m_diff;
137         }
138      }
139
140      m_last_count = count;
141      v_out = m_is_7492 ? disc_7492_count[count] : count;
142
143      if (UNEXPECTED(count != last_count))
144      {
145         /* the x_time is only output if the output changed. */
146         switch (m_out_type)
147         {
148            case DISC_OUT_HAS_XTIME:
149               v_out += x_time;
150               break;
151            case DISC_OUT_IS_ENERGY:
152               if (x_time == 0) x_time = 1.0;
153               v_out = last_count;
154               if (count > last_count)
155                  v_out += (count - last_count) * x_time;
156               else
157                  v_out -= (last_count - count) * x_time;
158               break;
159         }
160      }
161      set_output(0, v_out);
162   }
163}
164
165DISCRETE_RESET(dss_counter)
166{
167   if ((int)DSS_COUNTER__CLOCK_TYPE & DISC_COUNTER_IS_7492)
168   {
169      m_is_7492    = 1;
170      m_clock_type = DSS_7492__CLOCK_TYPE;
171      m_max = 5;
172      m_min = 0;
173      m_diff = 6;
174   }
175   else
176   {
177      m_is_7492    = 0;
178      m_clock_type = DSS_COUNTER__CLOCK_TYPE;
179      m_max = DSS_COUNTER__MAX;
180      m_min = DSS_COUNTER__MIN;
181      m_diff = m_max - m_min + 1;
182   }
183
184
185   if (!m_is_7492 && (DSS_COUNTER__MAX < DSS_COUNTER__MIN))
186      fatalerror("MAX < MIN in NODE_%02d\n", this->index());
187
188   m_out_type    = m_clock_type & DISC_OUT_MASK;
189   m_clock_type &= DISC_CLK_MASK;
190
191   m_t_left = 0;
192   m_last_count = 0;
193   m_last_clock = 0;
194   set_output(0, DSS_COUNTER__INIT); /* count starts at reset value */
195}
196
197
198/************************************************************************
199 *
200 * DSS_LFSR_NOISE - Usage of node_description values for LFSR noise gen
201 *
202 * input0    - Enable input value
203 * input1    - Register reset
204 * input2    - Clock Input
205 * input3    - Amplitude input value
206 * input4    - Input feed bit
207 * input5    - Bias
208 *
209 * also passed dss_lfsr_context structure
210 *
211 ************************************************************************/
212#define DSS_LFSR_NOISE__ENABLE  DISCRETE_INPUT(0)
213#define DSS_LFSR_NOISE__RESET   DISCRETE_INPUT(1)
214#define DSS_LFSR_NOISE__CLOCK   DISCRETE_INPUT(2)
215#define DSS_LFSR_NOISE__AMP     DISCRETE_INPUT(3)
216#define DSS_LFSR_NOISE__FEED    DISCRETE_INPUT(4)
217#define DSS_LFSR_NOISE__BIAS    DISCRETE_INPUT(5)
218
219INLINE int dss_lfsr_function(discrete_device *dev, int myfunc, int in0, int in1, int bitmask)
220{
221   int retval;
222
223   in0 &= bitmask;
224   in1 &= bitmask;
225
226   switch(myfunc)
227   {
228      case DISC_LFSR_XOR:
229         retval = in0 ^ in1;
230         break;
231      case DISC_LFSR_OR:
232         retval = in0 | in1;
233         break;
234      case DISC_LFSR_AND:
235         retval = in0 & in1;
236         break;
237      case DISC_LFSR_XNOR:
238         retval = in0 ^ in1;
239         retval = retval ^ bitmask;  /* Invert output */
240         break;
241      case DISC_LFSR_NOR:
242         retval = in0 | in1;
243         retval = retval ^ bitmask;  /* Invert output */
244         break;
245      case DISC_LFSR_NAND:
246         retval = in0 & in1;
247         retval = retval ^ bitmask;  /* Invert output */
248         break;
249      case DISC_LFSR_IN0:
250         retval = in0;
251         break;
252      case DISC_LFSR_IN1:
253         retval = in1;
254         break;
255      case DISC_LFSR_NOT_IN0:
256         retval = in0 ^ bitmask;
257         break;
258      case DISC_LFSR_NOT_IN1:
259         retval = in1 ^ bitmask;
260         break;
261      case DISC_LFSR_REPLACE:
262         retval = in0 & ~in1;
263         retval = retval | in1;
264         break;
265      case DISC_LFSR_XOR_INV_IN0:
266         retval = in0 ^ bitmask; /* invert in0 */
267         retval = retval ^ in1;  /* xor in1 */
268         break;
269      case DISC_LFSR_XOR_INV_IN1:
270         retval = in1 ^ bitmask; /* invert in1 */
271         retval = retval ^ in0;  /* xor in0 */
272         break;
273      default:
274         dev->discrete_log("dss_lfsr_function - Invalid function type passed");
275         retval=0;
276         break;
277   }
278   return retval;
279}
280
281
282DISCRETE_STEP(dss_lfsr_noise)
283{
284   DISCRETE_DECLARE_INFO(discrete_lfsr_desc)
285
286   double cycles;
287   int clock, inc = 0;
288   int fb0, fb1, fbresult = 0, noise_feed;
289
290   if (info->clock_type == DISC_CLK_IS_FREQ)
291   {
292      /* We need to keep clocking the internal clock even if disabled. */
293      cycles = (m_t_left + this->sample_time()) / m_t_clock;
294      inc    = (int)cycles;
295      m_t_left = (cycles - inc) * m_t_clock;
296   }
297
298   /* Reset everything if necessary */
299   if(((DSS_LFSR_NOISE__RESET == 0) ? 0 : 1) == m_reset_on_high)
300   {
301      this->reset();
302      return;
303   }
304
305   switch (info->clock_type)
306   {
307      case DISC_CLK_ON_F_EDGE:
308      case DISC_CLK_ON_R_EDGE:
309         /* See if the clock has toggled to the proper edge */
310         clock = (DSS_LFSR_NOISE__CLOCK != 0);
311         if (m_last != clock)
312         {
313            m_last = clock;
314            if (info->clock_type == clock)
315            {
316               /* Toggled */
317               inc = 1;
318            }
319         }
320         break;
321
322      case DISC_CLK_BY_COUNT:
323         /* Clock number of times specified. */
324         inc = (int)DSS_LFSR_NOISE__CLOCK;
325         break;
326   }
327
328   if (inc > 0)
329   {
330      double v_out;
331
332      noise_feed = (DSS_LFSR_NOISE__FEED ? 0x01 : 0x00);
333      for (clock = 0; clock < inc; clock++)
334      {
335         /* Fetch the last feedback result */
336         fbresult = (m_lfsr_reg >> info->bitlength) & 0x01;
337
338         /* Stage 2 feedback combine fbresultNew with infeed bit */
339         fbresult = dss_lfsr_function(m_device, info->feedback_function1, fbresult, noise_feed, 0x01);
340
341         /* Stage 3 first we setup where the bit is going to be shifted into */
342         fbresult = fbresult * info->feedback_function2_mask;
343         /* Then we left shift the register, */
344         m_lfsr_reg = m_lfsr_reg << 1;
345         /* Now move the fbresult into the shift register and mask it to the bitlength */
346         m_lfsr_reg = dss_lfsr_function(m_device, info->feedback_function2, fbresult, m_lfsr_reg, (1 << info->bitlength) - 1 );
347
348         /* Now get and store the new feedback result */
349         /* Fetch the feedback bits */
350         fb0 = (m_lfsr_reg >> info->feedback_bitsel0) & 0x01;
351         fb1 = (m_lfsr_reg >> info->feedback_bitsel1) & 0x01;
352         /* Now do the combo on them */
353         fbresult = dss_lfsr_function(m_device, info->feedback_function0, fb0, fb1, 0x01);
354         m_lfsr_reg = dss_lfsr_function(m_device, DISC_LFSR_REPLACE, m_lfsr_reg, fbresult << info->bitlength, (2 << info->bitlength) - 1);
355
356      }
357      /* Now select the output bit */
358      if (m_out_is_f0)
359         v_out = fbresult & 0x01;
360      else
361         v_out = (m_lfsr_reg >> info->output_bit) & 0x01;
362
363      /* Final inversion if required */
364      if (m_invert_output) v_out = v_out ? 0 : 1;
365
366      /* Gain stage */
367      v_out = v_out ? DSS_LFSR_NOISE__AMP / 2 : -DSS_LFSR_NOISE__AMP / 2;
368      /* Bias input as required */
369      v_out = v_out + DSS_LFSR_NOISE__BIAS;
370
371      set_output(0, v_out);
372
373      /* output the lfsr reg ?*/
374      if (m_out_lfsr_reg)
375         set_output(1, (double) m_lfsr_reg);
376
377   }
378   if(!DSS_LFSR_NOISE__ENABLE)
379   {
380      set_output(0, 0);
381   }
382}
383
384DISCRETE_RESET(dss_lfsr_noise)
385{
386   DISCRETE_DECLARE_INFO(discrete_lfsr_desc)
387
388   int    fb0 , fb1, fbresult;
389   double v_out;
390
391   m_reset_on_high = (info->flags & DISC_LFSR_FLAG_RESET_TYPE_H) ? 1 : 0;
392   m_invert_output = info->flags & DISC_LFSR_FLAG_OUT_INVERT;
393   m_out_is_f0 = (info->flags & DISC_LFSR_FLAG_OUTPUT_F0) ? 1 : 0;
394   m_out_lfsr_reg = (info->flags & DISC_LFSR_FLAG_OUTPUT_SR_SN1) ? 1 : 0;
395
396   if ((info->clock_type < DISC_CLK_ON_F_EDGE) || (info->clock_type > DISC_CLK_IS_FREQ))
397      m_device->discrete_log("Invalid clock type passed in NODE_%d\n", this->index());
398
399   m_last = (DSS_COUNTER__CLOCK != 0);
400   if (info->clock_type == DISC_CLK_IS_FREQ) m_t_clock = 1.0 / DSS_LFSR_NOISE__CLOCK;
401   m_t_left = 0;
402
403   m_lfsr_reg = info->reset_value;
404
405   /* Now get and store the new feedback result */
406   /* Fetch the feedback bits */
407   fb0 = (m_lfsr_reg >> info->feedback_bitsel0) & 0x01;
408   fb1=(m_lfsr_reg >> info->feedback_bitsel1) & 0x01;
409   /* Now do the combo on them */
410   fbresult = dss_lfsr_function(m_device, info->feedback_function0, fb0, fb1, 0x01);
411   m_lfsr_reg=dss_lfsr_function(m_device, DISC_LFSR_REPLACE, m_lfsr_reg, fbresult << info->bitlength, (2<< info->bitlength ) - 1);
412
413   /* Now select and setup the output bit */
414   v_out = (m_lfsr_reg >> info->output_bit) & 0x01;
415
416   /* Final inversion if required */
417   if(info->flags & DISC_LFSR_FLAG_OUT_INVERT) v_out = v_out ? 0 : 1;
418
419   /* Gain stage */
420   v_out = v_out ? DSS_LFSR_NOISE__AMP / 2 : -DSS_LFSR_NOISE__AMP / 2;
421   /* Bias input as required */
422   v_out += DSS_LFSR_NOISE__BIAS;
423
424   set_output(0, v_out);
425   set_output(1, 0);
426}
427
428
429/************************************************************************
430 *
431 * DSS_NOISE - Usage of node_description values for white nose generator
432 *
433 * input0    - Enable input value
434 * input1    - Noise sample frequency
435 * input2    - Amplitude input value
436 * input3    - DC Bias value
437 *
438 ************************************************************************/
439#define DSS_NOISE__ENABLE   DISCRETE_INPUT(0)
440#define DSS_NOISE__FREQ     DISCRETE_INPUT(1)
441#define DSS_NOISE__AMP      DISCRETE_INPUT(2)
442#define DSS_NOISE__BIAS     DISCRETE_INPUT(3)
443
444DISCRETE_STEP(dss_noise)
445{
446   double v_out;
447
448   if(DSS_NOISE__ENABLE)
449   {
450      /* Only sample noise on rollover to next cycle */
451      if(m_phase > (2.0 * M_PI))
452      {
453         /* GCC's rand returns a RAND_MAX value of 0x7fff */
454         int newval = (m_device->machine().rand() & 0x7fff) - 16384;
455
456         /* make sure the peak to peak values are the amplitude */
457         v_out = DSS_NOISE__AMP / 2;
458         if (newval > 0)
459            v_out *= ((double)newval / 16383);
460         else
461            v_out *= ((double)newval / 16384);
462
463         /* Add DC Bias component */
464         v_out += DSS_NOISE__BIAS;
465         set_output(0, v_out);
466      }
467   }
468   else
469   {
470      set_output(0, 0);
471   }
472
473   /* Keep the new phasor in the 2Pi range.*/
474   m_phase = fmod(m_phase, 2.0 * M_PI);
475
476   /* The enable input only curtails output, phase rotation still occurs. */
477   /* We allow the phase to exceed 2Pi here, so we can tell when to sample the noise. */
478   m_phase += ((2.0 * M_PI * DSS_NOISE__FREQ) / this->sample_rate());
479}
480
481
482DISCRETE_RESET(dss_noise)
483{
484   m_phase=0;
485   this->step();
486}
487
488
489/************************************************************************
490 *
491 * DSS_NOTE - Note/tone generator
492 *
493 * input0    - Enable input value
494 * input1    - Clock Input
495 * input2    - data value
496 * input3    - Max count 1
497 * input4    - Max count 2
498 * input5    - Clock type
499 *
500 * Mar 2004, D Renaud.
501 ************************************************************************/
502   #define DSS_NOTE__ENABLE        DISCRETE_INPUT(0)
503   #define DSS_NOTE__CLOCK     DISCRETE_INPUT(1)
504   #define DSS_NOTE__DATA          DISCRETE_INPUT(2)
505   #define DSS_NOTE__MAX1          DISCRETE_INPUT(3)
506   #define DSS_NOTE__MAX2          DISCRETE_INPUT(4)
507   #define DSS_NOTE__CLOCK_TYPE    DISCRETE_INPUT(5)
508
509DISCRETE_STEP(dss_note)
510{
511   double  cycles;
512   int     clock  = 0, last_count2, inc = 0;
513   double  x_time = 0;
514   double  v_out;
515
516   if (m_clock_type == DISC_CLK_IS_FREQ)
517   {
518      /* We need to keep clocking the internal clock even if disabled. */
519      cycles = (m_t_left + this->sample_time()) / m_t_clock;
520      inc    = (int)cycles;
521      m_t_left = (cycles - inc) * m_t_clock;
522      if (inc) x_time = m_t_left / this->sample_time();
523   }
524   else
525   {
526      /* separate clock info from x_time info. */
527      clock = (int)DSS_NOTE__CLOCK;
528      x_time = DSS_NOTE__CLOCK - clock;
529   }
530
531   if (DSS_NOTE__ENABLE)
532   {
533      last_count2 = m_count2;
534
535      switch (m_clock_type)
536      {
537         case DISC_CLK_ON_F_EDGE:
538         case DISC_CLK_ON_R_EDGE:
539            /* See if the clock has toggled to the proper edge */
540            clock = (clock != 0);
541            if (m_last != clock)
542            {
543               m_last = clock;
544               if (m_clock_type == clock)
545               {
546                  /* Toggled */
547                  inc = 1;
548               }
549            }
550            break;
551
552         case DISC_CLK_BY_COUNT:
553            /* Clock number of times specified. */
554            inc = clock;
555            break;
556      }
557
558      /* Count output as long as the data loaded is not already equal to max 1 count. */
559      if (DSS_NOTE__DATA != DSS_NOTE__MAX1)
560      {
561         for (clock = 0; clock < inc; clock++)
562         {
563            m_count1++;
564            if (m_count1 > m_max1)
565            {
566               /* Max 1 count reached.  Load Data into counter. */
567               m_count1  = (int)DSS_NOTE__DATA;
568               m_count2 += 1;
569               if (m_count2 > m_max2) m_count2 = 0;
570            }
571         }
572      }
573
574      v_out = m_count2;
575      if (m_count2 != last_count2)
576      {
577         /* the x_time is only output if the output changed. */
578         switch (m_out_type)
579         {
580            case DISC_OUT_IS_ENERGY:
581               if (x_time == 0) x_time = 1.0;
582               v_out = last_count2;
583               if (m_count2 > last_count2)
584                  v_out += (m_count2 - last_count2) * x_time;
585               else
586                  v_out -= (last_count2 - m_count2) * x_time;
587               break;
588            case DISC_OUT_HAS_XTIME:
589               v_out += x_time;
590               break;
591         }
592      }
593      set_output(0, v_out);
594   }
595   else
596      set_output(0, 0);
597}
598
599DISCRETE_RESET(dss_note)
600{
601   m_clock_type = (int)DSS_NOTE__CLOCK_TYPE & DISC_CLK_MASK;
602   m_out_type   = (int)DSS_NOTE__CLOCK_TYPE & DISC_OUT_MASK;
603
604   m_last    = (DSS_NOTE__CLOCK != 0);
605   m_t_left  = 0;
606   m_t_clock = 1.0 / DSS_NOTE__CLOCK;
607
608   m_count1 = (int)DSS_NOTE__DATA;
609   m_count2 = 0;
610   m_max1   = (int)DSS_NOTE__MAX1;
611   m_max2   = (int)DSS_NOTE__MAX2;
612   set_output(0, 0);
613}
614
615/************************************************************************
616 *
617 * DSS_OP_AMP_OSC - Op Amp Oscillators
618 *
619 * input0    - Enable input value
620 * input1    - vMod1 (if needed)
621 * input2    - vMod2 (if needed)
622 *
623 * also passed discrete_op_amp_osc_info structure
624 *
625 * Mar 2004, D Renaud.
626 ************************************************************************/
627#define DSS_OP_AMP_OSC__ENABLE  DISCRETE_INPUT(0)
628#define DSS_OP_AMP_OSC__VMOD1   DISCRETE_INPUT(1)
629#define DSS_OP_AMP_OSC__VMOD2   DISCRETE_INPUT(2)
630
631/* The inputs on a norton op-amp are (info->vP - OP_AMP_NORTON_VBE) */
632/* which is the same as the output high voltage.  We will define them */
633/* the same to save a calculation step */
634#define DSS_OP_AMP_OSC_NORTON_VP_IN     m_v_out_high
635
636DISCRETE_STEP(dss_op_amp_osc)
637{
638   DISCRETE_DECLARE_INFO(discrete_op_amp_osc_info)
639
640   double i = 0;               /* Charging current created by vIn */
641   double v = 0;           /* all input voltages mixed */
642   double dt;              /* change in time */
643   double v_cap;           /* Current voltage on capacitor, before dt */
644   double v_cap_next = 0;  /* Voltage on capacitor, after dt */
645   double charge[2]  = {0};
646   double x_time  = 0;     /* time since change happened */
647   double exponent;
648   UINT8 force_charge = 0;
649   UINT8 enable = DSS_OP_AMP_OSC__ENABLE;
650   UINT8 update_exponent = 0;
651   UINT8 flip_flop = m_flip_flop;
652   int count_f = 0;
653   int count_r = 0;
654
655   double v_out = 0;
656
657   dt = this->sample_time();   /* Change in time */
658   v_cap = m_v_cap;    /* Set to voltage before change */
659
660   /* work out the charge currents/voltages. */
661   switch (m_type)
662   {
663      case DISC_OP_AMP_OSCILLATOR_VCO_1:
664         /* Work out the charge rates. */
665         /* i is not a current.  It is being used as a temp variable. */
666         i = DSS_OP_AMP_OSC__VMOD1 * m_temp1;
667         charge[0] = (DSS_OP_AMP_OSC__VMOD1 - i) / info->r1;
668         charge[1] = (i - (DSS_OP_AMP_OSC__VMOD1 * m_temp2)) / m_temp3;
669         break;
670
671      case DISC_OP_AMP_OSCILLATOR_1 | DISC_OP_AMP_IS_NORTON:
672      {
673         /* resistors can be nodes, so everything needs updating */
674         double i1, i2;
675         /* add in enable current if using real enable */
676         if (m_has_enable)
677         {
678            if (enable)
679               i = m_i_enable;
680            enable = 1;
681         }
682         /* Work out the charge rates. */
683         charge[0] = DSS_OP_AMP_OSC_NORTON_VP_IN / *m_r[1-1] - i;
684         charge[1] = (m_v_out_high - OP_AMP_NORTON_VBE) / *m_r[2-1] - charge[0];
685         /* Work out the Inverting Schmitt thresholds. */
686         i1 = DSS_OP_AMP_OSC_NORTON_VP_IN / *m_r[5-1];
687         i2 = (0.0 - OP_AMP_NORTON_VBE) / *m_r[4-1];
688         m_threshold_low  = (i1 + i2) * *m_r[3-1] + OP_AMP_NORTON_VBE;
689         i2 = (m_v_out_high - OP_AMP_NORTON_VBE) / *m_r[4-1];
690         m_threshold_high = (i1 + i2) * *m_r[3-1] + OP_AMP_NORTON_VBE;
691         break;
692      }
693
694      case DISC_OP_AMP_OSCILLATOR_VCO_1 | DISC_OP_AMP_IS_NORTON:
695         /* Millman the input voltages. */
696         if (info->r7 == 0)
697         {
698            /* No r7 means that the modulation circuit is fed directly into the circuit. */
699            v = DSS_OP_AMP_OSC__VMOD1;
700         }
701         else
702         {
703            /* we need to mix any bias and all modulation voltages together. */
704            i  = m_i_fixed;
705            i += DSS_OP_AMP_OSC__VMOD1 / info->r7;
706            if (info->r8 != 0)
707               i += DSS_OP_AMP_OSC__VMOD2 / info->r8;
708            v  = i * m_r_total;
709         }
710
711         /* Work out the charge rates. */
712         v -= OP_AMP_NORTON_VBE;
713         charge[0] = v / info->r1;
714         charge[1] = v / info->r2 - charge[0];
715
716         /* use the real enable circuit */
717         force_charge = !enable;
718         enable = 1;
719         break;
720
721      case DISC_OP_AMP_OSCILLATOR_VCO_2 | DISC_OP_AMP_IS_NORTON:
722         /* Work out the charge rates. */
723         i = DSS_OP_AMP_OSC__VMOD1 / info->r1;
724         charge[0] = i - m_temp1;
725         charge[1] = m_temp2 - i;
726         /* if the negative pin current is less then the positive pin current, */
727         /* then the osc is disabled and the cap keeps charging */
728         if (charge[0] < 0)
729         {
730            force_charge =  1;
731            charge[0]  *= -1;
732         }
733         break;
734
735      case DISC_OP_AMP_OSCILLATOR_VCO_3 | DISC_OP_AMP_IS_NORTON:
736         /* start with fixed bias */
737         charge[0] = m_i_fixed;
738         /* add in enable current if using real enable */
739         if (m_has_enable)
740         {
741            if (enable)
742               charge[0] -= m_i_enable;
743            enable = 1;
744         }
745         /* we need to mix any bias and all modulation voltages together. */
746         v = DSS_OP_AMP_OSC__VMOD1 - OP_AMP_NORTON_VBE;
747         if (v < 0) v = 0;
748         charge[0] += v / info->r1;
749         if (info->r6 != 0)
750         {
751            v = DSS_OP_AMP_OSC__VMOD2 - OP_AMP_NORTON_VBE;
752            charge[0] += v / info->r6;
753         }
754         charge[1] = m_temp1 - charge[0];
755         break;
756   }
757
758   if (!enable)
759   {
760      /* we will just output 0 for oscillators that have no real enable. */
761      set_output(0, 0);
762      return;
763   }
764
765   /* Keep looping until all toggling in time sample is used up. */
766   do
767   {
768      if (m_is_linear_charge)
769      {
770         if ((flip_flop ^ m_flip_flop_xor) || force_charge)
771         {
772            /* Charging */
773            /* iC=C*dv/dt  works out to dv=iC*dt/C */
774            v_cap_next = v_cap + (charge[1] * dt / info->c);
775            dt = 0;
776
777            /* has it charged past upper limit? */
778            if (v_cap_next > m_threshold_high)
779            {
780               flip_flop = m_flip_flop_xor;
781               if (flip_flop)
782                  count_r++;
783               else
784                  count_f++;
785               if (force_charge)
786               {
787                  /* we need to keep charging the cap to the max thereby disabling the circuit */
788                  if (v_cap_next > m_v_out_high)
789                     v_cap_next = m_v_out_high;
790               }
791               else
792               {
793                  /* calculate the overshoot time */
794                  dt = info->c * (v_cap_next - m_threshold_high) / charge[1];
795                  x_time = dt;
796                  v_cap_next = m_threshold_high;
797               }
798            }
799         }
800         else
801         {
802            /* Discharging */
803            v_cap_next = v_cap - (charge[0] * dt / info->c);
804            dt     = 0;
805
806            /* has it discharged past lower limit? */
807            if (v_cap_next < m_threshold_low)
808            {
809               flip_flop = !m_flip_flop_xor;
810               if (flip_flop)
811                  count_r++;
812               else
813                  count_f++;
814               /* calculate the overshoot time */
815               dt = info->c * (m_threshold_low - v_cap_next) / charge[0];
816               x_time = dt;
817               v_cap_next = m_threshold_low;
818            }
819         }
820      }
821      else    /* non-linear charge */
822      {
823         if (update_exponent)
824            exponent = RC_CHARGE_EXP_DT(m_charge_rc[flip_flop], dt);
825         else
826            exponent = m_charge_exp[flip_flop];
827
828         v_cap_next = v_cap + ((m_charge_v[flip_flop] - v_cap) * exponent);
829         dt = 0;
830
831         if (flip_flop)
832         {
833            /* Has it charged past upper limit? */
834            if (v_cap_next > m_threshold_high)
835            {
836               dt = m_charge_rc[1]  * log(1.0 / (1.0 - ((v_cap_next - m_threshold_high) / (m_v_out_high - v_cap))));
837               x_time = dt;
838               v_cap_next = m_threshold_high;
839               flip_flop = 0;
840               count_f++;
841               update_exponent = 1;
842            }
843         }
844         else
845         {
846            /* has it discharged past lower limit? */
847            if (v_cap_next < m_threshold_low)
848            {
849               dt = m_charge_rc[0] * log(1.0 / (1.0 - ((m_threshold_low - v_cap_next) / v_cap)));
850               x_time = dt;
851               v_cap_next = m_threshold_low;
852               flip_flop = 1;
853               count_r++;
854               update_exponent = 1;
855            }
856         }
857      }
858      v_cap = v_cap_next;
859   } while(dt);
860   if (v_cap > m_v_out_high)
861      v_cap = m_v_out_high;
862   if (v_cap < 0)
863      v_cap = 0;
864   m_v_cap = v_cap;
865
866   x_time = dt / this->sample_time();
867
868   switch (m_output_type)
869   {
870      case DISC_OP_AMP_OSCILLATOR_OUT_CAP:
871         v_out = v_cap;
872         break;
873      case DISC_OP_AMP_OSCILLATOR_OUT_ENERGY:
874         if (x_time == 0) x_time = 1.0;
875         v_out = m_v_out_high * (flip_flop ? x_time : (1.0 - x_time));
876         break;
877      case DISC_OP_AMP_OSCILLATOR_OUT_SQW:
878         if (count_f + count_r >= 2)
879            /* force at least 1 toggle */
880            v_out = m_flip_flop ? 0 : m_v_out_high;
881         else
882            v_out = flip_flop * m_v_out_high;
883         break;
884      case DISC_OP_AMP_OSCILLATOR_OUT_COUNT_F_X:
885         v_out = count_f ? count_f + x_time : count_f;
886         break;
887      case DISC_OP_AMP_OSCILLATOR_OUT_COUNT_R_X:
888         v_out =  count_r ? count_r + x_time : count_r;
889         break;
890      case DISC_OP_AMP_OSCILLATOR_OUT_LOGIC_X:
891         v_out = m_flip_flop + x_time;
892         break;
893   }
894   set_output(0, v_out);
895   m_flip_flop = flip_flop;
896}
897
898#define DIODE_DROP  0.7
899
900DISCRETE_RESET(dss_op_amp_osc)
901{
902   DISCRETE_DECLARE_INFO(discrete_op_amp_osc_info)
903
904   const double *r_info_ptr;
905   int loop;
906
907   double i1 = 0;  /* inverting input current */
908   double i2 = 0;  /* non-inverting input current */
909
910   /* link to resistor static or node values */
911   r_info_ptr    = &info->r1;
912   for (loop = 0; loop < 8; loop ++)
913   {
914      m_r[loop] = m_device->node_output_ptr(*r_info_ptr);
915      if (m_r[loop] == NULL)
916         m_r[loop] = r_info_ptr;
917      r_info_ptr++;
918   }
919
920   m_is_linear_charge = 1;
921   m_output_type = info->type & DISC_OP_AMP_OSCILLATOR_OUT_MASK;
922   m_type        = info->type & DISC_OP_AMP_OSCILLATOR_TYPE_MASK;
923   m_charge_rc[0] = 0;
924   m_charge_rc[1] = 0;
925   m_charge_v[0] = 0;
926   m_charge_v[1] = 0;
927   m_i_fixed = 0;
928   m_has_enable = 0;
929
930   switch (m_type)
931   {
932      case DISC_OP_AMP_OSCILLATOR_VCO_1:
933         /* The charge rates vary depending on vMod so they are not precalculated. */
934         /* Charges while FlipFlop High */
935         m_flip_flop_xor = 0;
936         /* Work out the Non-inverting Schmitt thresholds. */
937         m_temp1 = (info->vP / 2) / info->r4;
938         m_temp2 = (info->vP - OP_AMP_VP_RAIL_OFFSET) / info->r3;
939         m_temp3 = 1.0 / (1.0 / info->r3 + 1.0 / info->r4);
940         m_threshold_low  =  m_temp1 * m_temp3;
941         m_threshold_high = (m_temp1 + m_temp2) * m_temp3;
942         /* There is no charge on the cap so the schmitt goes high at init. */
943         m_flip_flop = 1;
944         /* Setup some commonly used stuff */
945         m_temp1 = info->r5 / (info->r2 + info->r5);         /* voltage ratio across r5 */
946         m_temp2 = info->r6 / (info->r1 + info->r6);         /* voltage ratio across r6 */
947         m_temp3 = 1.0 / (1.0 / info->r1 + 1.0 / info->r6);  /* input resistance when r6 switched in */
948         break;
949
950      case DISC_OP_AMP_OSCILLATOR_1 | DISC_OP_AMP_IS_NORTON:
951         /* Charges while FlipFlop High */
952         m_flip_flop_xor = 0;
953         /* There is no charge on the cap so the schmitt inverter goes high at init. */
954         m_flip_flop = 1;
955         /* setup current if using real enable */
956         if (info->r6 > 0)
957         {
958            m_has_enable = 1;
959            m_i_enable = (info->vP - OP_AMP_NORTON_VBE) / (info->r6 + RES_K(1));
960         }
961         break;
962
963      case DISC_OP_AMP_OSCILLATOR_2 | DISC_OP_AMP_IS_NORTON:
964         m_is_linear_charge = 0;
965         /* First calculate the parallel charge resistors and volatges. */
966         /* We can cheat and just calcuate the charges in the working area. */
967         /* The thresholds are well past the effect of the voltage drop */
968         /* and the component tolerances far exceed the .5V charge difference */
969         if (info->r1 != 0)
970         {
971            m_charge_rc[0] = 1.0 / info->r1;
972            m_charge_rc[1] = 1.0 / info->r1;
973            m_charge_v[1] = (info->vP - OP_AMP_NORTON_VBE) / info->r1;
974         }
975         if (info->r5 != 0)
976         {
977            m_charge_rc[0] += 1.0 / info->r5;
978            m_charge_v[0] = DIODE_DROP / info->r5;
979         }
980         if (info->r6 != 0)
981         {
982            m_charge_rc[1] += 1.0 / info->r6;
983            m_charge_v[1] += (info->vP - OP_AMP_NORTON_VBE - DIODE_DROP) / info->r6;
984         }
985         m_charge_rc[0] += 1.0 / info->r2;
986         m_charge_rc[0] = 1.0 / m_charge_rc[0];
987         m_charge_v[0] += OP_AMP_NORTON_VBE / info->r2;
988         m_charge_v[0] *= m_charge_rc[0];
989         m_charge_rc[1] += 1.0 / info->r2;
990         m_charge_rc[1] = 1.0 / m_charge_rc[1];
991         m_charge_v[1] += OP_AMP_NORTON_VBE / info->r2;
992         m_charge_v[1] *= m_charge_rc[1];
993
994         m_charge_rc[0] *= info->c;
995         m_charge_rc[1] *= info->c;
996         m_charge_exp[0] = RC_CHARGE_EXP(m_charge_rc[0]);
997         m_charge_exp[1] = RC_CHARGE_EXP(m_charge_rc[1]);
998         m_threshold_low  = (info->vP - OP_AMP_NORTON_VBE) / info->r4;
999         m_threshold_high = m_threshold_low + (info->vP - 2 * OP_AMP_NORTON_VBE) / info->r3;;
1000         m_threshold_low  = m_threshold_low * info->r2 + OP_AMP_NORTON_VBE;
1001         m_threshold_high = m_threshold_high * info->r2 + OP_AMP_NORTON_VBE;
1002
1003         /* There is no charge on the cap so the schmitt inverter goes high at init. */
1004         m_flip_flop = 1;
1005         break;
1006
1007      case DISC_OP_AMP_OSCILLATOR_VCO_1 | DISC_OP_AMP_IS_NORTON:
1008         /* Charges while FlipFlop Low */
1009         m_flip_flop_xor = 1;
1010         /* There is no charge on the cap so the schmitt goes low at init. */
1011         m_flip_flop = 0;
1012         /* The charge rates vary depending on vMod so they are not precalculated. */
1013         /* But we can precalculate the fixed currents. */
1014         if (info->r6 != 0) m_i_fixed += info->vP / info->r6;
1015         m_i_fixed += OP_AMP_NORTON_VBE / info->r1;
1016         m_i_fixed += OP_AMP_NORTON_VBE / info->r2;
1017         /* Work out the input resistance to be used later to calculate the Millman voltage. */
1018         m_r_total = 1.0 / info->r1 + 1.0 / info->r2 + 1.0 / info->r7;
1019         if (info->r6) m_r_total += 1.0 / info->r6;
1020         if (info->r8) m_r_total += 1.0 / info->r8;
1021         m_r_total = 1.0 / m_r_total;
1022         /* Work out the Non-inverting Schmitt thresholds. */
1023         i1 = (info->vP - OP_AMP_NORTON_VBE) / info->r5;
1024         i2 = (info->vP - OP_AMP_NORTON_VBE - OP_AMP_NORTON_VBE) / info->r4;
1025         m_threshold_low = (i1 - i2) * info->r3 + OP_AMP_NORTON_VBE;
1026         i2 = (0.0 - OP_AMP_NORTON_VBE) / info->r4;
1027         m_threshold_high = (i1 - i2) * info->r3 + OP_AMP_NORTON_VBE;
1028         break;
1029
1030      case DISC_OP_AMP_OSCILLATOR_VCO_2 | DISC_OP_AMP_IS_NORTON:
1031         /* Charges while FlipFlop High */
1032         m_flip_flop_xor = 0;
1033         /* There is no charge on the cap so the schmitt inverter goes high at init. */
1034         m_flip_flop = 1;
1035         /* Work out the charge rates. */
1036         m_temp1 = (info->vP - OP_AMP_NORTON_VBE) / info->r2;
1037         m_temp2 = (info->vP - OP_AMP_NORTON_VBE) * (1.0 / info->r2 + 1.0 / info->r6);
1038         /* Work out the Inverting Schmitt thresholds. */
1039         i1 = (info->vP - OP_AMP_NORTON_VBE) / info->r5;
1040         i2 = (0.0 - OP_AMP_NORTON_VBE) / info->r4;
1041         m_threshold_low = (i1 + i2) * info->r3 + OP_AMP_NORTON_VBE;
1042         i2 = (info->vP - OP_AMP_NORTON_VBE - OP_AMP_NORTON_VBE) / info->r4;
1043         m_threshold_high = (i1 + i2) * info->r3 + OP_AMP_NORTON_VBE;
1044         break;
1045
1046      case DISC_OP_AMP_OSCILLATOR_VCO_3 | DISC_OP_AMP_IS_NORTON:
1047         /* Charges while FlipFlop High */
1048         m_flip_flop_xor = 0;
1049         /* There is no charge on the cap so the schmitt inverter goes high at init. */
1050         m_flip_flop = 1;
1051         /* setup current if using real enable */
1052         if (info->r8 > 0)
1053         {
1054            m_has_enable = 1;
1055            m_i_enable = (info->vP - OP_AMP_NORTON_VBE) / (info->r8 + RES_K(1));
1056         }
1057         /* Work out the charge rates. */
1058         /* The charge rates vary depending on vMod so they are not precalculated. */
1059         /* But we can precalculate the fixed currents. */
1060         if (info->r7 != 0) m_i_fixed = (info->vP - OP_AMP_NORTON_VBE) / info->r7;
1061         m_temp1 = (info->vP - OP_AMP_NORTON_VBE - OP_AMP_NORTON_VBE) / info->r2;
1062         /* Work out the Inverting Schmitt thresholds. */
1063         i1 = (info->vP - OP_AMP_NORTON_VBE) / info->r5;
1064         i2 = (0.0 - OP_AMP_NORTON_VBE) / info->r4;
1065         m_threshold_low = (i1 + i2) * info->r3 + OP_AMP_NORTON_VBE;
1066         i2 = (info->vP - OP_AMP_NORTON_VBE - OP_AMP_NORTON_VBE) / info->r4;
1067         m_threshold_high = (i1 + i2) * info->r3 + OP_AMP_NORTON_VBE;
1068         break;
1069   }
1070
1071   m_v_out_high = info->vP - ((m_type & DISC_OP_AMP_IS_NORTON) ? OP_AMP_NORTON_VBE : OP_AMP_VP_RAIL_OFFSET);
1072   m_v_cap      = 0;
1073
1074   this->step();
1075}
1076
1077
1078/************************************************************************
1079 *
1080 * DSS_SAWTOOTHWAVE - Usage of node_description values for step function
1081 *
1082 * input0    - Enable input value
1083 * input1    - Frequency input value
1084 * input2    - Amplitde input value
1085 * input3    - DC Bias Value
1086 * input4    - Gradient
1087 * input5    - Initial Phase
1088 *
1089 ************************************************************************/
1090#define DSS_SAWTOOTHWAVE__ENABLE    DISCRETE_INPUT(0)
1091#define DSS_SAWTOOTHWAVE__FREQ      DISCRETE_INPUT(1)
1092#define DSS_SAWTOOTHWAVE__AMP       DISCRETE_INPUT(2)
1093#define DSS_SAWTOOTHWAVE__BIAS      DISCRETE_INPUT(3)
1094#define DSS_SAWTOOTHWAVE__GRAD      DISCRETE_INPUT(4)
1095#define DSS_SAWTOOTHWAVE__PHASE     DISCRETE_INPUT(5)
1096
1097DISCRETE_STEP(dss_sawtoothwave)
1098{
1099   double v_out;
1100
1101   if(DSS_SAWTOOTHWAVE__ENABLE)
1102   {
1103      v_out = (m_type == 0) ? m_phase * (DSS_SAWTOOTHWAVE__AMP / (2.0 * M_PI)) : DSS_SAWTOOTHWAVE__AMP - (m_phase * (DSS_SAWTOOTHWAVE__AMP / (2.0 * M_PI)));
1104      v_out -= DSS_SAWTOOTHWAVE__AMP / 2.0;
1105      /* Add DC Bias component */
1106      v_out = v_out + DSS_SAWTOOTHWAVE__BIAS;
1107   }
1108   else
1109   {
1110      v_out = 0;
1111   }
1112   set_output(0, v_out);
1113
1114   /* Work out the phase step based on phase/freq & sample rate */
1115   /* The enable input only curtails output, phase rotation     */
1116   /* still occurs                                              */
1117   /*     phase step = 2Pi/(output period/sample period)        */
1118   /*                    boils out to                           */
1119   /*     phase step = (2Pi*output freq)/sample freq)           */
1120   /* Also keep the new phasor in the 2Pi range.                */
1121   m_phase = fmod((m_phase + ((2.0 * M_PI * DSS_SAWTOOTHWAVE__FREQ) / this->sample_rate())), 2.0 * M_PI);
1122}
1123
1124DISCRETE_RESET(dss_sawtoothwave)
1125{
1126   double start;
1127
1128   /* Establish starting phase, convert from degrees to radians */
1129   start = (DSS_SAWTOOTHWAVE__PHASE / 360.0) * (2.0 * M_PI);
1130   /* Make sure its always mod 2Pi */
1131   m_phase = fmod(start, 2.0 * M_PI);
1132
1133   /* Invert gradient depending on sawtooth type /|/|/|/|/| or |\|\|\|\|\ */
1134   m_type = (DSS_SAWTOOTHWAVE__GRAD) ? 1 : 0;
1135
1136   /* Step the node to set the output */
1137   this->step();
1138}
1139
1140
1141/************************************************************************
1142 *
1143 * DSS_SCHMITT_OSC - Schmitt feedback oscillator
1144 *
1145 * input0    - Enable input value
1146 * input1    - Vin
1147 * input2    - Amplitude
1148 *
1149 * also passed discrete_schmitt_osc_disc structure
1150 *
1151 * Mar 2004, D Renaud.
1152 ************************************************************************/
1153#define DSS_SCHMITT_OSC__ENABLE (int)DISCRETE_INPUT(0)
1154#define DSS_SCHMITT_OSC__VIN    DISCRETE_INPUT(1)
1155#define DSS_SCHMITT_OSC__AMP    DISCRETE_INPUT(2)
1156
1157DISCRETE_STEP(dss_schmitt_osc)
1158{
1159   DISCRETE_DECLARE_INFO(discrete_schmitt_osc_desc)
1160
1161   double supply, v_cap, new_vCap, t, exponent;
1162   double v_out = 0;
1163
1164   /* We will always oscillate.  The enable just affects the output. */
1165   v_cap    = m_v_cap;
1166   exponent = m_exponent;
1167
1168   /* Keep looping until all toggling in time sample is used up. */
1169   do
1170   {
1171      t = 0;
1172      /* The charging voltage to the cap is the sum of the input voltage and the gate
1173       * output voltage in the ratios determined by their resistors in a divider network.
1174       * The input voltage is selectable as straight voltage in or logic level that will
1175       * use vGate as its voltage.  Note that ration_in is just the ratio of the total
1176       * voltage and needs to be multipled by the input voltage.  ratio_feedback has
1177       * already been multiplied by vGate to save time because that voltage never changes. */
1178      supply   = m_input_is_voltage ? m_ration_in * DSS_SCHMITT_OSC__VIN : (DSS_SCHMITT_OSC__VIN ? m_ration_in * info->vGate : 0);
1179      supply  += (m_state ? m_ratio_feedback : 0);
1180      new_vCap = v_cap + ((supply - v_cap) * exponent);
1181      if (m_state)
1182      {
1183         /* Charging */
1184         /* has it charged past upper limit? */
1185         if (new_vCap > info->trshRise)
1186         {
1187            /* calculate the overshoot time */
1188            t = m_rc * log(1.0 / (1.0 - ((new_vCap - info->trshRise) / (info->vGate - v_cap))));
1189            /* calculate new exponent because of reduced time */
1190            exponent = RC_CHARGE_EXP_DT(m_rc, t);
1191            v_cap    = new_vCap = info->trshRise;
1192            m_state = 0;
1193         }
1194      }
1195      else
1196      {
1197         /* Discharging */
1198         /* has it discharged past lower limit? */
1199         if (new_vCap < info->trshFall)
1200         {
1201            /* calculate the overshoot time */
1202            t = m_rc * log(1.0 / (1.0 - ((info->trshFall - new_vCap) / v_cap)));
1203            /* calculate new exponent because of reduced time */
1204            exponent = RC_CHARGE_EXP_DT(m_rc, t);
1205            v_cap    = new_vCap = info->trshFall;
1206            m_state = 1;
1207         }
1208      }
1209   } while(t);
1210
1211   m_v_cap = new_vCap;
1212
1213   switch (m_enable_type)
1214   {
1215      case DISC_SCHMITT_OSC_ENAB_IS_AND:
1216         v_out = DSS_SCHMITT_OSC__ENABLE && m_state;
1217         break;
1218      case DISC_SCHMITT_OSC_ENAB_IS_NAND:
1219         v_out = !(DSS_SCHMITT_OSC__ENABLE && m_state);
1220         break;
1221      case DISC_SCHMITT_OSC_ENAB_IS_OR:
1222         v_out = DSS_SCHMITT_OSC__ENABLE || m_state;
1223         break;
1224      case DISC_SCHMITT_OSC_ENAB_IS_NOR:
1225         v_out = !(DSS_SCHMITT_OSC__ENABLE || m_state);
1226         break;
1227   }
1228   v_out *= DSS_SCHMITT_OSC__AMP;
1229   set_output(0, v_out);
1230}
1231
1232DISCRETE_RESET(dss_schmitt_osc)
1233{
1234   DISCRETE_DECLARE_INFO(discrete_schmitt_osc_desc)
1235
1236   double rSource;
1237
1238   m_enable_type      =  info->options & DISC_SCHMITT_OSC_ENAB_MASK;
1239   m_input_is_voltage = (info->options & DISC_SCHMITT_OSC_IN_IS_VOLTAGE) ? 1 : 0;
1240
1241   /* The 2 resistors make a voltage divider, so their ratios add together
1242    * to make the charging voltage. */
1243   m_ration_in      = info->rFeedback / (info->rIn + info->rFeedback);
1244   m_ratio_feedback = info->rIn / (info->rIn + info->rFeedback) * info->vGate;
1245
1246   /* The voltage source resistance works out to the 2 resistors in parallel.
1247    * So use this for the RC charge constant. */
1248   rSource     = 1.0 / ((1.0 / info->rIn) + (1.0 / info->rFeedback));
1249   m_rc = rSource * info->c;
1250   m_exponent = RC_CHARGE_EXP(m_rc);
1251
1252   /* Cap is at 0V on power up.  Causing output to be high. */
1253   m_v_cap = 0;
1254   m_state = 1;
1255
1256   set_output(0, info->options ? 0 : DSS_SCHMITT_OSC__AMP);
1257}
1258
1259
1260/************************************************************************
1261 *
1262 * DSS_SINEWAVE - Usage of node_description values for step function
1263 *
1264 * input0    - Enable input value
1265 * input1    - Frequency input value
1266 * input2    - Amplitude input value
1267 * input3    - DC Bias
1268 * input4    - Starting phase
1269 *
1270 ************************************************************************/
1271#define DSS_SINEWAVE__ENABLE    DISCRETE_INPUT(0)
1272#define DSS_SINEWAVE__FREQ      DISCRETE_INPUT(1)
1273#define DSS_SINEWAVE__AMPL      DISCRETE_INPUT(2)
1274#define DSS_SINEWAVE__BIAS      DISCRETE_INPUT(3)
1275#define DSS_SINEWAVE__PHASE     DISCRETE_INPUT(4)
1276
1277DISCRETE_STEP(dss_sinewave)
1278{
1279   /* Set the output */
1280   if(DSS_SINEWAVE__ENABLE)
1281   {
1282      set_output(0, (DSS_SINEWAVE__AMPL / 2.0) * sin(m_phase) + DSS_SINEWAVE__BIAS);
1283      /* Add DC Bias component */
1284   }
1285   else
1286   {
1287      set_output(0, 0);
1288   }
1289
1290   /* Work out the phase step based on phase/freq & sample rate */
1291   /* The enable input only curtails output, phase rotation     */
1292   /* still occurs                                              */
1293   /*     phase step = 2Pi/(output period/sample period)        */
1294   /*                    boils out to                           */
1295   /*     phase step = (2Pi*output freq)/sample freq)           */
1296   /* Also keep the new phasor in the 2Pi range.                */
1297   m_phase=fmod((m_phase + ((2.0 * M_PI * DSS_SINEWAVE__FREQ) / this->sample_rate())), 2.0 * M_PI);
1298}
1299
1300DISCRETE_RESET(dss_sinewave)
1301{
1302   double start;
1303
1304   /* Establish starting phase, convert from degrees to radians */
1305   start = (DSS_SINEWAVE__PHASE / 360.0) * (2.0 * M_PI);
1306   /* Make sure its always mod 2Pi */
1307   m_phase = fmod(start, 2.0 * M_PI);
1308   /* Step the output to make it correct */
1309   this->step();
1310}
1311
1312
1313/************************************************************************
1314 *
1315 * DSS_SQUAREWAVE - Usage of node_description values for step function
1316 *
1317 * input0    - Enable input value
1318 * input1    - Frequency input value
1319 * input2    - Amplitude input value
1320 * input3    - Duty Cycle
1321 * input4    - DC Bias level
1322 * input5    - Start Phase
1323 *
1324 ************************************************************************/
1325#define DSS_SQUAREWAVE__ENABLE  DISCRETE_INPUT(0)
1326#define DSS_SQUAREWAVE__FREQ    DISCRETE_INPUT(1)
1327#define DSS_SQUAREWAVE__AMP     DISCRETE_INPUT(2)
1328#define DSS_SQUAREWAVE__DUTY    DISCRETE_INPUT(3)
1329#define DSS_SQUAREWAVE__BIAS    DISCRETE_INPUT(4)
1330#define DSS_SQUAREWAVE__PHASE   DISCRETE_INPUT(5)
1331
1332DISCRETE_STEP(dss_squarewave)
1333{
1334   /* Establish trigger phase from duty */
1335   m_trigger=((100-DSS_SQUAREWAVE__DUTY)/100)*(2.0*M_PI);
1336
1337   /* Set the output */
1338   if(DSS_SQUAREWAVE__ENABLE)
1339   {
1340      if(m_phase>m_trigger)
1341         set_output(0, DSS_SQUAREWAVE__AMP / 2.0 + DSS_SQUAREWAVE__BIAS);
1342      else
1343         set_output(0, - DSS_SQUAREWAVE__AMP / 2.0 + DSS_SQUAREWAVE__BIAS);
1344      /* Add DC Bias component */
1345   }
1346   else
1347   {
1348      set_output(0, 0);
1349   }
1350
1351   /* Work out the phase step based on phase/freq & sample rate */
1352   /* The enable input only curtails output, phase rotation     */
1353   /* still occurs                                              */
1354   /*     phase step = 2Pi/(output period/sample period)        */
1355   /*                    boils out to                           */
1356   /*     phase step = (2Pi*output freq)/sample freq)           */
1357   /* Also keep the new phasor in the 2Pi range.                */
1358   m_phase=fmod(m_phase + ((2.0 * M_PI * DSS_SQUAREWAVE__FREQ) / this->sample_rate()), 2.0 * M_PI);
1359}
1360
1361DISCRETE_RESET(dss_squarewave)
1362{
1363   double start;
1364
1365   /* Establish starting phase, convert from degrees to radians */
1366   start = (DSS_SQUAREWAVE__PHASE / 360.0) * (2.0 * M_PI);
1367   /* Make sure its always mod 2Pi */
1368   m_phase = fmod(start, 2.0 * M_PI);
1369
1370   /* Step the output */
1371   this->step();
1372}
1373
1374/************************************************************************
1375 *
1376 * DSS_SQUAREWFIX - Usage of node_description values for step function
1377 *
1378 * input0    - Enable input value
1379 * input1    - Frequency input value
1380 * input2    - Amplitude input value
1381 * input3    - Duty Cycle
1382 * input4    - DC Bias level
1383 * input5    - Start Phase
1384 *
1385 ************************************************************************/
1386#define DSS_SQUAREWFIX__ENABLE  DISCRETE_INPUT(0)
1387#define DSS_SQUAREWFIX__FREQ    DISCRETE_INPUT(1)
1388#define DSS_SQUAREWFIX__AMP     DISCRETE_INPUT(2)
1389#define DSS_SQUAREWFIX__DUTY    DISCRETE_INPUT(3)
1390#define DSS_SQUAREWFIX__BIAS    DISCRETE_INPUT(4)
1391#define DSS_SQUAREWFIX__PHASE   DISCRETE_INPUT(5)
1392
1393DISCRETE_STEP(dss_squarewfix)
1394{
1395   m_t_left -= m_sample_step;
1396
1397   /* The enable input only curtails output, phase rotation still occurs */
1398   while (m_t_left <= 0)
1399   {
1400      m_flip_flop = m_flip_flop ? 0 : 1;
1401      m_t_left   += m_flip_flop ? m_t_on : m_t_off;
1402   }
1403
1404   if(DSS_SQUAREWFIX__ENABLE)
1405   {
1406      /* Add gain and DC Bias component */
1407
1408      m_t_off  = 1.0 / DSS_SQUAREWFIX__FREQ;  /* cycle time */
1409      m_t_on   = m_t_off * (DSS_SQUAREWFIX__DUTY / 100.0);
1410      m_t_off -= m_t_on;
1411
1412      set_output(0, (m_flip_flop ? DSS_SQUAREWFIX__AMP / 2.0 : -(DSS_SQUAREWFIX__AMP / 2.0)) + DSS_SQUAREWFIX__BIAS);
1413   }
1414   else
1415   {
1416      set_output(0, 0);
1417   }
1418}
1419
1420DISCRETE_RESET(dss_squarewfix)
1421{
1422   m_sample_step = 1.0 / this->sample_rate();
1423   m_flip_flop   = 1;
1424
1425   /* Do the intial time shift and convert freq to off/on times */
1426   m_t_off   = 1.0 / DSS_SQUAREWFIX__FREQ; /* cycle time */
1427   m_t_left  = DSS_SQUAREWFIX__PHASE / 360.0;  /* convert start phase to % */
1428   m_t_left  = m_t_left - (int)m_t_left;   /* keep % between 0 & 1 */
1429   m_t_left  = (m_t_left < 0) ? 1.0 + m_t_left : m_t_left; /* if - then flip to + phase */
1430   m_t_left *= m_t_off;
1431   m_t_on    = m_t_off * (DSS_SQUAREWFIX__DUTY / 100.0);
1432   m_t_off  -= m_t_on;
1433
1434   m_t_left = -m_t_left;
1435
1436   /* toggle output and work out intial time shift */
1437   while (m_t_left <= 0)
1438   {
1439      m_flip_flop = m_flip_flop ? 0 : 1;
1440      m_t_left   += m_flip_flop ? m_t_on : m_t_off;
1441   }
1442
1443   /* Step the output */
1444   this->step();
1445}
1446
1447
1448/************************************************************************
1449 *
1450 * DSS_SQUAREWAVE2 - Usage of node_description values
1451 *
1452 * input0    - Enable input value
1453 * input1    - Amplitude input value
1454 * input2    - OFF Time
1455 * input3    - ON Time
1456 * input4    - DC Bias level
1457 * input5    - Initial Time Shift
1458 *
1459 ************************************************************************/
1460#define DSS_SQUAREWAVE2__ENABLE DISCRETE_INPUT(0)
1461#define DSS_SQUAREWAVE2__AMP    DISCRETE_INPUT(1)
1462#define DSS_SQUAREWAVE2__T_OFF  DISCRETE_INPUT(2)
1463#define DSS_SQUAREWAVE2__T_ON   DISCRETE_INPUT(3)
1464#define DSS_SQUAREWAVE2__BIAS   DISCRETE_INPUT(4)
1465#define DSS_SQUAREWAVE2__SHIFT  DISCRETE_INPUT(5)
1466
1467DISCRETE_STEP(dss_squarewave2)
1468{
1469   double newphase;
1470
1471   if(DSS_SQUAREWAVE2__ENABLE)
1472   {
1473      /* Establish trigger phase from time periods */
1474      m_trigger = (DSS_SQUAREWAVE2__T_OFF / (DSS_SQUAREWAVE2__T_OFF + DSS_SQUAREWAVE2__T_ON)) * (2.0 * M_PI);
1475
1476      /* Work out the phase step based on phase/freq & sample rate */
1477      /* The enable input only curtails output, phase rotation     */
1478      /* still occurs                                              */
1479
1480      /*     phase step = 2Pi/(output period/sample period)        */
1481      /*                    boils out to                           */
1482      /*     phase step = 2Pi/(output period*sample freq)          */
1483      newphase = m_phase + ((2.0 * M_PI) / ((DSS_SQUAREWAVE2__T_OFF + DSS_SQUAREWAVE2__T_ON) * this->sample_rate()));
1484      /* Keep the new phasor in the 2Pi range.*/
1485      m_phase = fmod(newphase, 2.0 * M_PI);
1486
1487      /* Add DC Bias component */
1488      if(m_phase>m_trigger)
1489         set_output(0, DSS_SQUAREWAVE2__AMP / 2.0  + DSS_SQUAREWAVE2__BIAS);
1490      else
1491         set_output(0, -DSS_SQUAREWAVE2__AMP / 2.0 + DSS_SQUAREWAVE2__BIAS);
1492   }
1493   else
1494   {
1495      set_output(0, 0);
1496   }
1497}
1498
1499DISCRETE_RESET(dss_squarewave2)
1500{
1501   double start;
1502
1503   /* Establish starting phase, convert from degrees to radians */
1504   /* Only valid if we have set the on/off time                 */
1505   if((DSS_SQUAREWAVE2__T_OFF + DSS_SQUAREWAVE2__T_ON) != 0.0)
1506      start = (DSS_SQUAREWAVE2__SHIFT / (DSS_SQUAREWAVE2__T_OFF + DSS_SQUAREWAVE2__T_ON)) * (2.0 * M_PI);
1507   else
1508      start = 0.0;
1509   /* Make sure its always mod 2Pi */
1510   m_phase = fmod(start, 2.0 * M_PI);
1511
1512   /* Step the output */
1513   this->step();
1514}
1515
1516/************************************************************************
1517 *
1518 * DSS_INVERTER_OSC - Usage of node_description values
1519 *
1520 * input0    - Enable input value
1521 * input1    - RC Resistor
1522 * input2    - RP Resistor
1523 * input3    - C Capacitor
1524 * input4    - Desc
1525 *
1526 ************************************************************************/
1527
1528/*
1529 * Taken from the transfer characteristerics diagram in CD4049UB datasheet (TI)
1530 * There is no default trigger point and vI-vO is a continuous function
1531 */
1532
1533inline double DISCRETE_CLASS_FUNC(dss_inverter_osc, tftab)(double x)
1534{
1535   DISCRETE_DECLARE_INFO(description)
1536
1537   x = x / info->vB;
1538   if (x > 0)
1539      return info->vB * exp(-mc_tf_a * pow(x, mc_tf_b));
1540   else
1541      return info->vB;
1542}
1543
1544inline double DISCRETE_CLASS_FUNC(dss_inverter_osc, tf)(double x)
1545{
1546   DISCRETE_DECLARE_INFO(description)
1547
1548   if (x < 0.0)
1549      return info->vB;
1550   else if (x <= info->vB)
1551      return mc_tf_tab[(int)((double)(DSS_INV_TAB_SIZE - 1) * x / info->vB)];
1552   else
1553      return mc_tf_tab[DSS_INV_TAB_SIZE - 1];
1554}
1555
1556DISCRETE_STEP(dss_inverter_osc)
1557{
1558   DISCRETE_DECLARE_INFO(description)
1559   double diff, vG1, vG2, vG3, vI;
1560   double vMix, rMix;
1561   int clamped;
1562   double v_out;
1563
1564   /* Get new state */
1565   vI = mc_v_cap + mc_v_g2_old;
1566   switch (info->options & TYPE_MASK)
1567   {
1568      case IS_TYPE1:
1569      case IS_TYPE3:
1570         vG1 = this->tf(vI);
1571         vG2 = this->tf(vG1);
1572         vG3 = this->tf(vG2);
1573         break;
1574      case IS_TYPE2:
1575         vG1 = 0;
1576         vG3 = this->tf(vI);
1577         vG2 = this->tf(vG3);
1578         break;
1579      case IS_TYPE4:
1580         vI  = MIN(I_ENABLE(), vI + 0.7);
1581         vG1 = 0;
1582         vG3 = this->tf(vI);
1583         vG2 = this->tf(vG3);
1584         break;
1585      case IS_TYPE5:
1586         vI  = MAX(I_ENABLE(), vI - 0.7);
1587         vG1 = 0;
1588         vG3 = this->tf(vI);
1589         vG2 = this->tf(vG3);
1590         break;
1591      default:
1592         fatalerror("DISCRETE_INVERTER_OSC - Wrong type on NODE_%02d\n", this->index());
1593   }
1594
1595   clamped = 0;
1596   if (info->clamp >= 0.0)
1597   {
1598      if (vI < -info->clamp)
1599      {
1600         vI = -info->clamp;
1601         clamped = 1;
1602      }
1603      else if (vI > info->vB+info->clamp)
1604      {
1605         vI = info->vB + info->clamp;
1606         clamped = 1;
1607      }
1608   }
1609
1610   switch (info->options & TYPE_MASK)
1611   {
1612      case IS_TYPE1:
1613      case IS_TYPE2:
1614      case IS_TYPE3:
1615         if (clamped)
1616         {
1617            double ratio = mc_rp / (mc_rp + mc_r1);
1618            diff = vG3 * (ratio)
1619                  - (mc_v_cap + vG2)
1620                  + vI * (1.0 - ratio);
1621            diff = diff - diff * mc_wc;
1622         }
1623         else
1624         {
1625            diff = vG3 - (mc_v_cap + vG2);
1626            diff = diff - diff * mc_w;
1627         }
1628         break;
1629      case IS_TYPE4:
1630         /*  FIXME handle r2 = 0  */
1631         rMix = (mc_r1 * mc_r2) / (mc_r1 + mc_r2);
1632         vMix = rMix* ((vG3 - vG2) / mc_r1 + (I_MOD() -vG2) / mc_r2);
1633         if (vMix < (vI-vG2-0.7))
1634         {
1635            rMix = 1.0 / rMix + 1.0 / mc_rp;
1636            rMix = 1.0 / rMix;
1637            vMix = rMix* ( (vG3-vG2) / mc_r1 + (I_MOD() - vG2) / mc_r2
1638                  + (vI - 0.7 - vG2) / mc_rp);
1639         }
1640         diff = vMix - mc_v_cap;
1641         diff = diff - diff * exp(-this->sample_time() / (mc_c * rMix));
1642         break;
1643      case IS_TYPE5:
1644         /*  FIXME handle r2 = 0  */
1645         rMix = (mc_r1 * mc_r2) / (mc_r1 + mc_r2);
1646         vMix = rMix* ((vG3 - vG2) / mc_r1 + (I_MOD() - vG2) / mc_r2);
1647         if (vMix > (vI -vG2 + 0.7))
1648         {
1649            rMix = 1.0 / rMix + 1.0 / mc_rp;
1650            rMix = 1.0 / rMix;
1651            vMix = rMix * ( (vG3 - vG2) / mc_r1 + (I_MOD() - vG2) / mc_r2
1652                  + (vI + 0.7 - vG2) / mc_rp);
1653         }
1654         diff = vMix - mc_v_cap;
1655         diff = diff - diff * exp(-this->sample_time()/(mc_c * rMix));
1656         break;
1657      default:
1658         fatalerror("DISCRETE_INVERTER_OSC - Wrong type on NODE_%02d\n", this->index());
1659   }
1660
1661   mc_v_cap   += diff;
1662   mc_v_g2_old = vG2;
1663
1664   if ((info->options & TYPE_MASK) == IS_TYPE3)
1665      v_out = vG1;
1666   else
1667      v_out = vG3;
1668
1669   if (info->options & OUT_IS_LOGIC)
1670      v_out = (v_out > info->vInFall);
1671
1672   set_output(0, v_out);
1673}
1674
1675DISCRETE_RESET(dss_inverter_osc)
1676{
1677   DISCRETE_DECLARE_INFO(description)
1678
1679   int i;
1680
1681   /* exponent */
1682   mc_w  = exp(-this->sample_time() / (I_RC() * I_C()));
1683   mc_wc = exp(-this->sample_time() / ((I_RC() * I_RP()) / (I_RP() + I_RC()) * I_C()));
1684   set_output(0, 0);
1685   mc_v_cap    = 0;
1686   mc_v_g2_old = 0;
1687   mc_rp   = I_RP();
1688   mc_r1   = I_RC();
1689   mc_r2   = I_R2();
1690   mc_c    = I_C();
1691   mc_tf_b = (log(0.0 - log(info->vOutLow/info->vB)) - log(0.0 - log((info->vOutHigh/info->vB))) ) / log(info->vInRise / info->vInFall);
1692   mc_tf_a = log(0.0 - log(info->vOutLow/info->vB)) - mc_tf_b * log(info->vInRise/info->vB);
1693   mc_tf_a = exp(mc_tf_a);
1694
1695   for (i = 0; i < DSS_INV_TAB_SIZE; i++)
1696   {
1697      mc_tf_tab[i] = this->tftab((double)i / (double)(DSS_INV_TAB_SIZE - 1) * info->vB);
1698   }
1699}
1700
1701/************************************************************************
1702 *
1703 * DSS_TRIANGLEWAVE - Usage of node_description values for step function
1704 *
1705 * input0    - Enable input value
1706 * input1    - Frequency input value
1707 * input2    - Amplitde input value
1708 * input3    - DC Bias value
1709 * input4    - Initial Phase
1710 *
1711 ************************************************************************/
1712#define DSS_TRIANGLEWAVE__ENABLE    DISCRETE_INPUT(0)
1713#define DSS_TRIANGLEWAVE__FREQ      DISCRETE_INPUT(1)
1714#define DSS_TRIANGLEWAVE__AMP       DISCRETE_INPUT(2)
1715#define DSS_TRIANGLEWAVE__BIAS      DISCRETE_INPUT(3)
1716#define DSS_TRIANGLEWAVE__PHASE     DISCRETE_INPUT(4)
1717
1718DISCRETE_STEP(dss_trianglewave)
1719{
1720   if(DSS_TRIANGLEWAVE__ENABLE)
1721   {
1722      double v_out = m_phase < M_PI ? (DSS_TRIANGLEWAVE__AMP * (m_phase / (M_PI / 2.0) - 1.0)) / 2.0 :
1723                           (DSS_TRIANGLEWAVE__AMP * (3.0 - m_phase / (M_PI / 2.0))) / 2.0 ;
1724
1725      /* Add DC Bias component */
1726      v_out  += DSS_TRIANGLEWAVE__BIAS;
1727      set_output(0, v_out);
1728   }
1729   else
1730   {
1731      set_output(0, 0);
1732   }
1733
1734   /* Work out the phase step based on phase/freq & sample rate */
1735   /* The enable input only curtails output, phase rotation     */
1736   /* still occurs                                              */
1737   /*     phase step = 2Pi/(output period/sample period)        */
1738   /*                    boils out to                           */
1739   /*     phase step = (2Pi*output freq)/sample freq)           */
1740   /* Also keep the new phasor in the 2Pi range.                */
1741   m_phase=fmod((m_phase + ((2.0 * M_PI * DSS_TRIANGLEWAVE__FREQ) / this->sample_rate())), 2.0 * M_PI);
1742}
1743
1744DISCRETE_RESET(dss_trianglewave)
1745{
1746   double start;
1747
1748   /* Establish starting phase, convert from degrees to radians */
1749   start = (DSS_TRIANGLEWAVE__PHASE / 360.0) * (2.0 * M_PI);
1750   /* Make sure its always mod 2Pi */
1751   m_phase=fmod(start, 2.0 * M_PI);
1752
1753   /* Step to set the output */
1754   this->step();
1755}
1756
1757
1758/************************************************************************
1759 *
1760 * DSS_ADSR - Attack Decay Sustain Release
1761 *
1762 * input0    - Enable input value
1763 * input1    - Trigger value
1764 * input2    - gain scaling factor
1765 *
1766 ************************************************************************/
1767#define DSS_ADSR__ENABLE    DISCRETE_INPUT(0)
1768
1769DISCRETE_STEP(dss_adsrenv)
1770{
1771   if(DSS_ADSR__ENABLE)
1772   {
1773      set_output(0, 0);
1774   }
1775   else
1776   {
1777      set_output(0, 0);
1778   }
1779}
1780
1781
1782DISCRETE_RESET(dss_adsrenv)
1783{
1784   this->step();
1785}
Property changes on: trunk/src/emu/sound/disc_wav.inc
Added: svn:mime-type
   + text/plain
Added: svn:eol-style
   + native
trunk/src/emu/sound/disc_dev.inc
r0r28732
1/************************************************************************
2 *
3 *  MAME - Discrete sound system emulation library
4 *
5 *  Written by Keith Wilkins (mame@dysfunction.demon.co.uk)
6 *
7 *  (c) K.Wilkins 2000
8 *  (c) D.Renaud 2003-2004
9 *
10 ************************************************************************
11 *
12 * DSD_555_ASTBL         - NE555 Simulation - Astable mode
13 * DSD_555_MSTBL         - NE555 Simulation - Monostable mode
14 * DSD_555_CC            - NE555 Constant Current VCO
15 * DSD_555_VCO1          - Op-Amp linear ramp based 555 VCO
16 * DSD_566               - NE566 Simulation
17 * DSD_LS624             - 74LS624/629 Simulation
18 *
19 ************************************************************************
20 *
21 * You will notice that the code for a lot of these routines are similar.
22 * I tried to make a common charging routine, but there are too many
23 * minor differences that affect each module.
24 *
25 ************************************************************************/
26
27#define DEFAULT_555_BLEED_R RES_M(10)
28
29/************************************************************************
30 *
31 * DSD_555_ASTBL -  - 555 Astable simulation
32 *
33 * input[0]    - Reset value
34 * input[1]    - R1 value
35 * input[2]    - R2 value
36 * input[3]    - C value
37 * input[4]    - Control Voltage value
38 *
39 * also passed discrete_555_desc structure
40 *
41 * Jan 2004, D Renaud.
42 ************************************************************************/
43#define DSD_555_ASTBL__RESET    (! DISCRETE_INPUT(0))
44#define DSD_555_ASTBL__R1       DISCRETE_INPUT(1)
45#define DSD_555_ASTBL__R2       DISCRETE_INPUT(2)
46#define DSD_555_ASTBL__C        DISCRETE_INPUT(3)
47#define DSD_555_ASTBL__CTRLV    DISCRETE_INPUT(4)
48
49/* bit mask of the above RC inputs */
50#define DSD_555_ASTBL_RC_MASK   0x0e
51
52/* charge/discharge constants */
53#define DSD_555_ASTBL_T_RC_BLEED        (DEFAULT_555_BLEED_R * DSD_555_ASTBL__C)
54/* Use quick charge if specified. */
55#define DSD_555_ASTBL_T_RC_CHARGE       ((DSD_555_ASTBL__R1 + ((info->options & DISC_555_ASTABLE_HAS_FAST_CHARGE_DIODE) ? 0 : DSD_555_ASTBL__R2)) * DSD_555_ASTBL__C)
56#define DSD_555_ASTBL_T_RC_DISCHARGE    (DSD_555_ASTBL__R2 * DSD_555_ASTBL__C)
57
58DISCRETE_STEP(dsd_555_astbl)
59{
60   DISCRETE_DECLARE_INFO(discrete_555_desc)
61
62   int     count_f = 0;
63   int     count_r = 0;
64   double  dt;                             /* change in time */
65   double  x_time  = 0;                    /* time since change happened */
66   double  v_cap   = m_cap_voltage;    /* Current voltage on capacitor, before dt */
67   double  v_cap_next = 0;                 /* Voltage on capacitor, after dt */
68   double  v_charge, exponent = 0;
69   UINT8   flip_flop = m_flip_flop;
70   UINT8   update_exponent = 0;
71   double  v_out = 0.0;
72
73   /* put commonly used stuff in local variables for speed */
74   double  threshold = m_threshold;
75   double  trigger   = m_trigger;
76
77   if(DSD_555_ASTBL__RESET)
78   {
79      /* We are in RESET */
80      set_output(0, 0);
81      m_flip_flop   = 1;
82      m_cap_voltage = 0;
83      return;
84   }
85
86   /* Check: if the Control Voltage node is connected. */
87   if (m_use_ctrlv)
88   {
89      /* If CV is less then .25V, the circuit will oscillate way out of range.
90       * So we will just ignore it when it happens. */
91      if (DSD_555_ASTBL__CTRLV < .25) return;
92      /* If it is a node then calculate thresholds based on Control Voltage */
93      threshold = DSD_555_ASTBL__CTRLV;
94      trigger   = DSD_555_ASTBL__CTRLV / 2.0;
95      /* Since the thresholds may have changed we need to update the FF */
96      if (v_cap >= threshold)
97      {
98         flip_flop = 0;
99         count_f++;
100      }
101      else
102      if (v_cap <= trigger)
103      {
104         flip_flop = 1;
105         count_r++;
106      }
107   }
108
109   /* get the v_charge and update each step if it is a node */
110   if (m_v_charge_node != NULL)
111   {
112      v_charge = *m_v_charge_node;
113      if (info->options & DISC_555_ASTABLE_HAS_FAST_CHARGE_DIODE) v_charge -= 0.5;
114   }
115   else
116      v_charge = m_v_charge;
117
118
119   /* Calculate future capacitor voltage.
120    * ref@ http://www.physics.rutgers.edu/ugrad/205/capacitance.html
121    * The formulas from the ref pages have been modified to reflect that we are stepping the change.
122    * dt = time of sample (1/sample frequency)
123    * VC = Voltage across capacitor
124    * VC' = Future voltage across capacitor
125    * Vc = Voltage change
126    * Vr = is the voltage across the resistor.  For charging it is Vcc - VC.  Discharging it is VC - 0.
127    * R = R1+R2 (for charging)  R = R2 for discharging.
128    * Vc = Vr*(1-exp(-dt/(R*C)))
129    * VC' = VC + Vc (for charging) VC' = VC - Vc for discharging.
130    *
131    * We will also need to calculate the amount of time we overshoot the thresholds
132    * dt = amount of time we overshot
133    * Vc = voltage change overshoot
134    * dt = R*C(log(1/(1-(Vc/Vr))))
135    */
136
137   dt = this->sample_time();
138
139   /* Sometimes a switching network is used to setup the capacitance.
140    * These may select no capacitor, causing oscillation to stop.
141    */
142   if (DSD_555_ASTBL__C == 0)
143   {
144      flip_flop = 1;
145      /* The voltage goes high because the cap circuit is open. */
146      v_cap_next = v_charge;
147      v_cap      = v_charge;
148      m_cap_voltage = 0;
149   }
150   else
151   {
152      /* Update charge contstants and exponents if nodes changed */
153      if (m_has_rc_nodes && (DSD_555_ASTBL__R1 != m_last_r1 || DSD_555_ASTBL__C != m_last_c || DSD_555_ASTBL__R2 != m_last_r2))
154      {
155         m_t_rc_bleed  = DSD_555_ASTBL_T_RC_BLEED;
156         m_t_rc_charge = DSD_555_ASTBL_T_RC_CHARGE;
157         m_t_rc_discharge = DSD_555_ASTBL_T_RC_DISCHARGE;
158         m_exp_bleed  = RC_CHARGE_EXP(m_t_rc_bleed);
159         m_exp_charge = RC_CHARGE_EXP(m_t_rc_charge);
160         m_exp_discharge = RC_CHARGE_EXP(m_t_rc_discharge);
161         m_last_r1 = DSD_555_ASTBL__R1;
162         m_last_r2 = DSD_555_ASTBL__R2;
163         m_last_c  = DSD_555_ASTBL__C;
164      }
165      /* Keep looping until all toggling in time sample is used up. */
166      do
167      {
168         if (flip_flop)
169         {
170            if (DSD_555_ASTBL__R1 == 0)
171            {
172               /* Oscillation disabled because there is no longer any charge resistor. */
173               /* Bleed the cap due to circuit losses. */
174               if (update_exponent)
175                  exponent = RC_CHARGE_EXP_DT(m_t_rc_bleed, dt);
176               else
177                  exponent = m_exp_bleed;
178               v_cap_next = v_cap - (v_cap * exponent);
179               dt = 0;
180            }
181            else
182            {
183               /* Charging */
184               if (update_exponent)
185                  exponent = RC_CHARGE_EXP_DT(m_t_rc_charge, dt);
186               else
187                  exponent = m_exp_charge;
188               v_cap_next = v_cap + ((v_charge - v_cap) * exponent);
189               dt = 0;
190
191               /* has it charged past upper limit? */
192               if (v_cap_next >= threshold)
193               {
194                  /* calculate the overshoot time */
195                  dt     = m_t_rc_charge  * log(1.0 / (1.0 - ((v_cap_next - threshold) / (v_charge - v_cap))));
196                  x_time = dt;
197                  v_cap_next  = threshold;
198                  flip_flop = 0;
199                  count_f++;
200                  update_exponent = 1;
201               }
202            }
203         }
204         else
205         {
206            /* Discharging */
207            if(DSD_555_ASTBL__R2 != 0)
208            {
209               if (update_exponent)
210                  exponent = RC_CHARGE_EXP_DT(m_t_rc_discharge, dt);
211               else
212                  exponent = m_exp_discharge;
213               v_cap_next = v_cap - (v_cap * exponent);
214               dt = 0;
215            }
216            else
217            {
218               /* no discharge resistor so we immediately discharge */
219               v_cap_next = trigger;
220            }
221
222            /* has it discharged past lower limit? */
223            if (v_cap_next <= trigger)
224            {
225               /* calculate the overshoot time */
226               if (v_cap_next < trigger)
227                  dt = m_t_rc_discharge  * log(1.0 / (1.0 - ((trigger - v_cap_next) / v_cap)));
228               x_time = dt;
229               v_cap_next  = trigger;
230               flip_flop = 1;
231               count_r++;
232               update_exponent = 1;
233            }
234         }
235         v_cap = v_cap_next;
236      } while(dt);
237
238      m_cap_voltage = v_cap;
239   }
240
241   /* Convert last switch time to a ratio */
242   x_time = x_time / this->sample_time();
243
244   switch (m_output_type)
245   {
246      case DISC_555_OUT_SQW:
247         if (count_f + count_r >= 2)
248            /* force at least 1 toggle */
249            v_out =  m_flip_flop ? 0 : m_v_out_high;
250         else
251            v_out =  flip_flop * m_v_out_high;
252         v_out += m_ac_shift;
253         break;
254      case DISC_555_OUT_CAP:
255         v_out =  v_cap;
256         /* Fake it to AC if needed */
257         if (m_output_is_ac)
258            v_out -= threshold * 3.0 /4.0;
259         break;
260      case DISC_555_OUT_ENERGY:
261         if (x_time == 0) x_time = 1.0;
262         v_out = m_v_out_high * (flip_flop ? x_time : (1.0 - x_time));
263         v_out += m_ac_shift;
264         break;
265      case DISC_555_OUT_LOGIC_X:
266         v_out =  flip_flop + x_time;
267         break;
268      case DISC_555_OUT_COUNT_F_X:
269         v_out = count_f ? count_f + x_time : count_f;
270         break;
271      case DISC_555_OUT_COUNT_R_X:
272         v_out =  count_r ? count_r + x_time : count_r;
273         break;
274      case DISC_555_OUT_COUNT_F:
275         v_out =  count_f;
276         break;
277      case DISC_555_OUT_COUNT_R:
278         v_out =  count_r;
279         break;
280   }
281   set_output(0, v_out);
282   m_flip_flop = flip_flop;
283}
284
285DISCRETE_RESET(dsd_555_astbl)
286{
287   DISCRETE_DECLARE_INFO(discrete_555_desc)
288
289   m_use_ctrlv   = (this->input_is_node() >> 4) & 1;
290   m_output_type = info->options & DISC_555_OUT_MASK;
291
292   /* Use the defaults or supplied values. */
293   m_v_out_high = (info->v_out_high == DEFAULT_555_HIGH) ? info->v_pos - 1.2 : info->v_out_high;
294
295   /* setup v_charge or node */
296   m_v_charge_node = m_device->node_output_ptr(info->v_charge);
297   if (m_v_charge_node == NULL)
298   {
299      m_v_charge   = (info->v_charge == DEFAULT_555_CHARGE) ? info->v_pos : info->v_charge;
300
301      if (info->options & DISC_555_ASTABLE_HAS_FAST_CHARGE_DIODE) m_v_charge -= 0.5;
302   }
303
304   if ((DSD_555_ASTBL__CTRLV != -1) && !m_use_ctrlv)
305   {
306      /* Setup based on supplied Control Voltage static value */
307      m_threshold = DSD_555_ASTBL__CTRLV;
308      m_trigger   = DSD_555_ASTBL__CTRLV / 2.0;
309   }
310   else
311   {
312      /* Setup based on v_pos power source */
313      m_threshold = info->v_pos * 2.0 / 3.0;
314      m_trigger   = info->v_pos / 3.0;
315   }
316
317   /* optimization if none of the values are nodes */
318   m_has_rc_nodes = 0;
319   if (this->input_is_node() & DSD_555_ASTBL_RC_MASK)
320      m_has_rc_nodes = 1;
321   else
322   {
323      m_t_rc_bleed  = DSD_555_ASTBL_T_RC_BLEED;
324      m_exp_bleed   = RC_CHARGE_EXP(m_t_rc_bleed);
325      m_t_rc_charge = DSD_555_ASTBL_T_RC_CHARGE;
326      m_exp_charge  = RC_CHARGE_EXP(m_t_rc_charge);
327      m_t_rc_discharge = DSD_555_ASTBL_T_RC_DISCHARGE;
328      m_exp_discharge  = RC_CHARGE_EXP(m_t_rc_discharge);
329   }
330
331   m_output_is_ac = info->options & DISC_555_OUT_AC;
332   /* Calculate DC shift needed to make squarewave waveform AC */
333   m_ac_shift = m_output_is_ac ? -m_v_out_high / 2.0 : 0;
334
335   m_flip_flop = 1;
336   m_cap_voltage = 0;
337
338   /* Step to set the output */
339   this->step();
340}
341
342
343/************************************************************************
344 *
345 * DSD_555_MSTBL - 555 Monostable simulation
346 *
347 * input[0]    - Reset value
348 * input[1]    - Trigger input
349 * input[2]    - R2 value
350 * input[3]    - C value
351 *
352 * also passed discrete_555_desc structure
353 *
354 * Oct 2004, D Renaud.
355 ************************************************************************/
356#define DSD_555_MSTBL__RESET    (! DISCRETE_INPUT(0))
357#define DSD_555_MSTBL__TRIGGER  DISCRETE_INPUT(1)
358#define DSD_555_MSTBL__R        DISCRETE_INPUT(2)
359#define DSD_555_MSTBL__C        DISCRETE_INPUT(3)
360
361/* bit mask of the above RC inputs */
362#define DSD_555_MSTBL_RC_MASK   0x0c
363
364DISCRETE_STEP(dsd_555_mstbl)
365{
366   DISCRETE_DECLARE_INFO(discrete_555_desc)
367
368   double v_cap;           /* Current voltage on capacitor, before dt */
369   double x_time = 0;      /* time since change happened */
370   double dt, exponent;
371   double out = 0;
372   int trigger = 0;
373   int trigger_type;
374   int update_exponent = m_has_rc_nodes;
375   int flip_flop;
376
377   if(UNEXPECTED(DSD_555_MSTBL__RESET))
378   {
379      /* We are in RESET */
380      set_output(0, 0);
381      m_flip_flop  = 0;
382      m_cap_voltage = 0;
383      return;
384   }
385
386   dt = this->sample_time();
387   flip_flop = m_flip_flop;
388   trigger_type = info->options;
389   v_cap = m_cap_voltage;
390
391   switch (trigger_type & DSD_555_TRIGGER_TYPE_MASK)
392   {
393      case DISC_555_TRIGGER_IS_LOGIC:
394         trigger = ((int)DSD_555_MSTBL__TRIGGER) ? 0 : 1;
395         if (UNEXPECTED(trigger))
396            x_time = 1.0 - DSD_555_MSTBL__TRIGGER;
397         break;
398      case DISC_555_TRIGGER_IS_VOLTAGE:
399         trigger = (int)(DSD_555_MSTBL__TRIGGER < m_trigger);
400         break;
401      case DISC_555_TRIGGER_IS_COUNT:
402         trigger = (int)DSD_555_MSTBL__TRIGGER;
403         if (UNEXPECTED(trigger))
404            x_time = DSD_555_MSTBL__TRIGGER - trigger;
405         break;
406   }
407
408   if (UNEXPECTED(trigger && !flip_flop && x_time != 0))
409   {
410      /* adjust sample to after trigger */
411      update_exponent = 1;
412      dt *= x_time;
413   }
414   x_time = 0;
415
416   if ((trigger_type & DISC_555_TRIGGER_DISCHARGES_CAP) && trigger)
417      m_cap_voltage = 0;
418
419   /* Wait for trigger */
420   if (UNEXPECTED(!flip_flop && trigger))
421   {
422      flip_flop = 1;
423      m_flip_flop = 1;
424   }
425
426   if (flip_flop)
427   {
428      /* Sometimes a switching network is used to setup the capacitance.
429       * These may select 'no' capacitor, causing oscillation to stop.
430       */
431      if (UNEXPECTED(DSD_555_MSTBL__C == 0))
432      {
433         /* The trigger voltage goes high because the cap circuit is open.
434          * and the cap discharges */
435         v_cap = info->v_pos;    /* needed for cap output type */
436         m_cap_voltage = 0;
437
438         if (!trigger)
439         {
440            flip_flop = 0;
441            m_flip_flop = 0;
442         }
443      }
444      else
445      {
446         /* Charging */
447         double v_diff = m_v_charge - v_cap;
448
449         if (UNEXPECTED(update_exponent))
450            exponent = RC_CHARGE_EXP_DT(DSD_555_MSTBL__R * DSD_555_MSTBL__C, dt);
451         else
452            exponent = m_exp_charge;
453         v_cap += v_diff * exponent;
454
455         /* Has it charged past upper limit? */
456         /* If trigger is still enabled, then we keep charging,
457          * regardless of threshold. */
458         if (UNEXPECTED((v_cap >= m_threshold) && !trigger))
459         {
460            dt = DSD_555_MSTBL__R * DSD_555_MSTBL__C  * log(1.0 / (1.0 - ((v_cap - m_threshold) / v_diff)));
461            x_time = 1.0 - dt / this->sample_time();
462            v_cap  = 0;
463            flip_flop = 0;
464            m_flip_flop = 0;
465         }
466         m_cap_voltage = v_cap;
467      }
468   }
469
470   switch (m_output_type)
471   {
472      case DISC_555_OUT_SQW:
473         out = flip_flop * m_v_out_high - m_ac_shift;
474         break;
475      case DISC_555_OUT_CAP:
476         if (x_time > 0)
477            out = v_cap * x_time;
478         else
479            out = v_cap;
480
481         out -= m_ac_shift;
482         break;
483      case DISC_555_OUT_ENERGY:
484         if (x_time > 0)
485            out = m_v_out_high * x_time;
486         else if (flip_flop)
487            out = m_v_out_high;
488         else
489            out = 0;
490
491         out -= m_ac_shift;
492         break;
493   }
494   set_output(0,  out);
495}
496
497DISCRETE_RESET(dsd_555_mstbl)
498{
499   DISCRETE_DECLARE_INFO(discrete_555_desc)
500
501   m_output_type = info->options & DISC_555_OUT_MASK;
502   if ((m_output_type == DISC_555_OUT_COUNT_F) || (m_output_type == DISC_555_OUT_COUNT_R))
503   {
504      m_device->discrete_log("Invalid Output type in NODE_%d.\n", this->index());
505      m_output_type = DISC_555_OUT_SQW;
506   }
507
508   /* Use the defaults or supplied values. */
509   m_v_out_high = (info->v_out_high == DEFAULT_555_HIGH) ? info->v_pos - 1.2 : info->v_out_high;
510   m_v_charge   = (info->v_charge   == DEFAULT_555_CHARGE) ? info->v_pos : info->v_charge;
511
512   /* Setup based on v_pos power source */
513   m_threshold = info->v_pos * 2.0 / 3.0;
514   m_trigger   = info->v_pos / 3.0;
515
516   /* Calculate DC shift needed to make waveform AC */
517   if (info->options & DISC_555_OUT_AC)
518   {
519      if (m_output_type == DISC_555_OUT_CAP)
520         m_ac_shift = m_threshold * 3.0 /4.0;
521      else
522         m_ac_shift = m_v_out_high / 2.0;
523   }
524   else
525      m_ac_shift = 0;
526
527   m_trig_is_logic       = (info->options & DISC_555_TRIGGER_IS_VOLTAGE) ? 0: 1;
528   m_trig_discharges_cap = (info->options & DISC_555_TRIGGER_DISCHARGES_CAP) ? 1: 0;
529
530   m_flip_flop   = 0;
531   m_cap_voltage = 0;
532
533   /* optimization if none of the values are nodes */
534   m_has_rc_nodes = 0;
535   if (this->input_is_node() & DSD_555_MSTBL_RC_MASK)
536      m_has_rc_nodes = 1;
537   else
538      m_exp_charge = RC_CHARGE_EXP(DSD_555_MSTBL__R * DSD_555_MSTBL__C);
539
540   set_output(0,  0);
541}
542
543
544/************************************************************************
545 *
546 * DSD_555_CC - Usage of node_description values
547 *
548 * input[0]    - Reset input value
549 * input[1]    - Voltage input for Constant current source.
550 * input[2]    - R value to set CC current.
551 * input[3]    - C value
552 * input[4]    - rBias value
553 * input[5]    - rGnd value
554 * input[6]    - rDischarge value
555 *
556 * also passed discrete_555_cc_desc structure
557 *
558 * Mar 2004, D Renaud.
559 ************************************************************************/
560#define DSD_555_CC__RESET   (! DISCRETE_INPUT(0))
561#define DSD_555_CC__VIN     DISCRETE_INPUT(1)
562#define DSD_555_CC__R       DISCRETE_INPUT(2)
563#define DSD_555_CC__C       DISCRETE_INPUT(3)
564#define DSD_555_CC__RBIAS   DISCRETE_INPUT(4)
565#define DSD_555_CC__RGND    DISCRETE_INPUT(5)
566#define DSD_555_CC__RDIS    DISCRETE_INPUT(6)
567
568/* bit mask of the above RC inputs not including DSD_555_CC__R */
569#define DSD_555_CC_RC_MASK  0x78
570
571/* charge/discharge constants */
572#define DSD_555_CC_T_RC_BLEED           (DEFAULT_555_BLEED_R * DSD_555_CC__C)
573#define DSD_555_CC_T_RC_DISCHARGE_01    (DSD_555_CC__RDIS * DSD_555_CC__C)
574#define DSD_555_CC_T_RC_DISCHARGE_NO_I  (DSD_555_CC__RGND * DSD_555_CC__C)
575#define DSD_555_CC_T_RC_CHARGE          (r_charge * DSD_555_CC__C)
576#define DSD_555_CC_T_RC_DISCHARGE       (r_discharge * DSD_555_CC__C)
577
578
579DISCRETE_STEP(dsd_555_cc)
580{
581   DISCRETE_DECLARE_INFO(discrete_555_cc_desc)
582
583   int     count_f  = 0;
584   int     count_r  = 0;
585   double  i;                  /* Charging current created by vIn */
586   double  r_charge = 0;       /* Equivalent charging resistor */
587   double  r_discharge = 0;    /* Equivalent discharging resistor */
588   double  vi     = 0;         /* Equivalent voltage from current source */
589   double  v_bias = 0;         /* Equivalent voltage from bias voltage */
590   double  v      = 0;         /* Equivalent voltage total from current source and bias circuit if used */
591   double  dt;                 /* change in time */
592   double  x_time = 0;         /* time since change happened */
593   double  t_rc ;              /* RC time constant */
594   double  v_cap;              /* Current voltage on capacitor, before dt */
595   double  v_cap_next = 0;     /* Voltage on capacitor, after dt */
596   double  v_vcharge_limit;    /* vIn and the junction voltage limit the max charging voltage from i */
597   double  r_temp;             /* play thing */
598   double  exponent;
599   UINT8   update_exponent, update_t_rc;
600   UINT8   flip_flop = m_flip_flop;
601
602   double v_out = 0;
603
604
605   if (UNEXPECTED(DSD_555_CC__RESET))
606   {
607      /* We are in RESET */
608      set_output(0, 0);
609      m_flip_flop   = 1;
610      m_cap_voltage = 0;
611      return;
612   }
613
614   dt    = this->sample_time();    /* Change in time */
615   v_cap = m_cap_voltage;  /* Set to voltage before change */
616   v_vcharge_limit = DSD_555_CC__VIN + info->v_cc_junction;    /* the max v_cap can be and still be charged by i */
617   /* Calculate charging current */
618   i = (m_v_cc_source - v_vcharge_limit) / DSD_555_CC__R;
619   if ( i < 0) i = 0;
620
621   if (info->options & DISCRETE_555_CC_TO_CAP)
622   {
623      vi = i * DSD_555_CC__RDIS;
624   }
625   else
626   {
627      switch (m_type) /* see dsd_555_cc_reset for descriptions */
628      {
629         case 1:
630            r_discharge = DSD_555_CC__RDIS;
631         case 0:
632            break;
633         case 3:
634            r_discharge = RES_2_PARALLEL(DSD_555_CC__RDIS, DSD_555_CC__RGND);
635         case 2:
636            r_charge = DSD_555_CC__RGND;
637            vi       = i * r_charge;
638            break;
639         case 4:
640            r_charge = DSD_555_CC__RBIAS;
641            vi       = i * r_charge;
642            v_bias   = info->v_pos;
643            break;
644         case 5:
645            r_charge = DSD_555_CC__RBIAS + DSD_555_CC__RDIS;
646            vi      = i * DSD_555_CC__RBIAS;
647            v_bias  = info->v_pos;
648            r_discharge = DSD_555_CC__RDIS;
649            break;
650         case 6:
651            r_charge = RES_2_PARALLEL(DSD_555_CC__RBIAS, DSD_555_CC__RGND);
652            vi      = i * r_charge;
653            v_bias  = info->v_pos * RES_VOLTAGE_DIVIDER(DSD_555_CC__RGND, DSD_555_CC__RBIAS);
654            break;
655         case 7:
656            r_temp   = DSD_555_CC__RBIAS + DSD_555_CC__RDIS;
657            r_charge = RES_2_PARALLEL(r_temp, DSD_555_CC__RGND);
658            r_temp  += DSD_555_CC__RGND;
659            r_temp   = DSD_555_CC__RGND / r_temp;   /* now has voltage divider ratio, not resistance */
660            vi      = i * DSD_555_CC__RBIAS * r_temp;
661            v_bias  = info->v_pos * r_temp;
662            r_discharge = RES_2_PARALLEL(DSD_555_CC__RGND, DSD_555_CC__RDIS);
663            break;
664      }
665   }
666
667   /* Keep looping until all toggling in time sample is used up. */
668   update_t_rc = m_has_rc_nodes;
669   update_exponent = update_t_rc;
670   do
671   {
672      if (m_type <= 1)
673      {
674         /* Standard constant current charge */
675         if (flip_flop)
676         {
677            if (i == 0)
678            {
679               /* No charging current, so we have to discharge the cap
680                * due to cap and circuit losses.
681                */
682               if (update_exponent)
683               {
684                  t_rc     = DSD_555_CC_T_RC_BLEED;
685                  exponent = RC_CHARGE_EXP_DT(t_rc, dt);
686               }
687               else
688                  exponent = m_exp_bleed;
689               v_cap_next = v_cap - (v_cap * exponent);
690               dt = 0;
691            }
692            else
693            {
694               /* Charging */
695               /* iC=C*dv/dt  works out to dv=iC*dt/C */
696               v_cap_next = v_cap + (i * dt / DSD_555_CC__C);
697               /* Yes, if the cap voltage has reached the max voltage it can,
698                * and the 555 threshold has not been reached, then oscillation stops.
699                * This is the way the actual electronics works.
700                * This is why you never play with the pots after being factory adjusted
701                * to work in the proper range. */
702               if (v_cap_next > v_vcharge_limit) v_cap_next = v_vcharge_limit;
703               dt = 0;
704
705               /* has it charged past upper limit? */
706               if (v_cap_next >= m_threshold)
707               {
708                  /* calculate the overshoot time */
709                  dt     = DSD_555_CC__C * (v_cap_next - m_threshold) / i;
710                  x_time = dt;
711                  v_cap_next = m_threshold;
712                  flip_flop = 0;
713                  count_f++;
714                  update_exponent = 1;
715               }
716            }
717         }
718         else if (DSD_555_CC__RDIS != 0)
719         {
720            /* Discharging */
721            if (update_t_rc)
722               t_rc = DSD_555_CC_T_RC_DISCHARGE_01;
723            else
724               t_rc = m_t_rc_discharge_01;
725            if (update_exponent)
726               exponent = RC_CHARGE_EXP_DT(t_rc, dt);
727            else
728               exponent = m_exp_discharge_01;
729
730            if (info->options & DISCRETE_555_CC_TO_CAP)
731            {
732               /* Asteroids - Special Case */
733               /* Charging in discharge mode */
734               /* If the cap voltage is past the current source charging limit
735                * then only the bias voltage will charge the cap. */
736               v          = (v_cap < v_vcharge_limit) ? vi : v_vcharge_limit;
737               v_cap_next = v_cap + ((v - v_cap) * exponent);
738            }
739            else
740            {
741               v_cap_next = v_cap - (v_cap * exponent);
742            }
743
744            dt = 0;
745            /* has it discharged past lower limit? */
746            if (v_cap_next <= m_trigger)
747            {
748               dt     = t_rc  * log(1.0 / (1.0 - ((m_trigger - v_cap_next) / v_cap)));
749               x_time = dt;
750               v_cap_next  = m_trigger;
751               flip_flop = 1;
752               count_r++;
753               update_exponent = 1;
754            }
755         }
756         else    /* Immediate discharge. No change in dt. */
757         {
758            x_time = dt;
759            v_cap_next = m_trigger;
760            flip_flop = 1;
761            count_r++;
762         }
763      }
764      else
765      {
766         /* The constant current gets changed to a voltage due to a load resistor. */
767         if (flip_flop)
768         {
769            if ((i == 0) && (DSD_555_CC__RBIAS == 0))
770            {
771               /* No charging current, so we have to discharge the cap
772                * due to rGnd.
773                */
774               if (update_t_rc)
775                  t_rc = DSD_555_CC_T_RC_DISCHARGE_NO_I;
776               else
777                  t_rc = m_t_rc_discharge_no_i;
778               if (update_exponent)
779                  exponent = RC_CHARGE_EXP_DT(t_rc, dt);
780               else
781                  exponent = m_exp_discharge_no_i;
782
783               v_cap_next = v_cap - (v_cap * exponent);
784               dt = 0;
785            }
786            else
787            {
788               /* Charging */
789               /* If the cap voltage is past the current source charging limit
790                * then only the bias voltage will charge the cap. */
791               v = v_bias;
792               if (v_cap < v_vcharge_limit) v += vi;
793               else if (m_type <= 3) v = v_vcharge_limit;
794
795               if (update_t_rc)
796                  t_rc = DSD_555_CC_T_RC_CHARGE;
797               else
798                  t_rc = m_t_rc_charge;
799               if (update_exponent)
800                  exponent = RC_CHARGE_EXP_DT(t_rc, dt);
801               else
802                  exponent = m_exp_charge;
803
804               v_cap_next = v_cap + ((v - v_cap) * exponent);
805               dt         = 0;
806
807               /* has it charged past upper limit? */
808               if (v_cap_next >= m_threshold)
809               {
810                  /* calculate the overshoot time */
811                  dt     = t_rc  * log(1.0 / (1.0 - ((v_cap_next - m_threshold) / (v - v_cap))));
812                  x_time = dt;
813                  v_cap_next = m_threshold;
814                  flip_flop = 0;
815                  count_f++;
816                  update_exponent = 1;
817               }
818            }
819         }
820         else /* Discharging */
821         if (r_discharge)
822         {
823            if (update_t_rc)
824               t_rc = DSD_555_CC_T_RC_DISCHARGE;
825            else
826               t_rc = m_t_rc_discharge;
827            if (update_exponent)
828               exponent = RC_CHARGE_EXP_DT(t_rc, dt);
829            else
830               exponent = m_exp_discharge;
831
832            v_cap_next = v_cap - (v_cap * exponent);
833            dt = 0;
834
835            /* has it discharged past lower limit? */
836            if (v_cap_next <= m_trigger)
837            {
838               /* calculate the overshoot time */
839               dt     = t_rc  * log(1.0 / (1.0 - ((m_trigger - v_cap_next) / v_cap)));
840               x_time = dt;
841               v_cap_next = m_trigger;
842               flip_flop = 1;
843               count_r++;
844               update_exponent = 1;
845            }
846         }
847         else    /* Immediate discharge. No change in dt. */
848         {
849            x_time = dt;
850            v_cap_next = m_trigger;
851            flip_flop = 1;
852            count_r++;
853         }
854      }
855      v_cap = v_cap_next;
856   } while(dt);
857
858   m_cap_voltage = v_cap;
859
860   /* Convert last switch time to a ratio */
861   x_time = x_time / this->sample_time();
862
863   switch (m_output_type)
864   {
865      case DISC_555_OUT_SQW:
866         if (count_f + count_r >= 2)
867            /* force at least 1 toggle */
868            v_out =  m_flip_flop ? 0 : m_v_out_high;
869         else
870            v_out = flip_flop * m_v_out_high;
871         /* Fake it to AC if needed */
872         v_out += m_ac_shift;
873         break;
874      case DISC_555_OUT_CAP:
875         v_out = v_cap + m_ac_shift;
876         break;
877      case DISC_555_OUT_ENERGY:
878         if (x_time == 0) x_time = 1.0;
879         v_out = m_v_out_high * (flip_flop ? x_time : (1.0 - x_time));
880         v_out += m_ac_shift;
881         break;
882      case DISC_555_OUT_LOGIC_X:
883         v_out = flip_flop + x_time;
884         break;
885      case DISC_555_OUT_COUNT_F_X:
886         v_out = count_f ? count_f + x_time : count_f;
887         break;
888      case DISC_555_OUT_COUNT_R_X:
889         v_out = count_r ? count_r + x_time : count_r;
890         break;
891      case DISC_555_OUT_COUNT_F:
892         v_out = count_f;
893         break;
894      case DISC_555_OUT_COUNT_R:
895         v_out = count_r;
896         break;
897   }
898   set_output(0, v_out);
899   m_flip_flop = flip_flop;
900}
901
902DISCRETE_RESET(dsd_555_cc)
903{
904   DISCRETE_DECLARE_INFO(discrete_555_cc_desc)
905
906   double  r_temp, r_discharge = 0, r_charge = 0;
907
908   m_flip_flop   = 1;
909   m_cap_voltage = 0;
910
911   m_output_type = info->options & DISC_555_OUT_MASK;
912
913   /* Use the defaults or supplied values. */
914   m_v_out_high  = (info->v_out_high  == DEFAULT_555_HIGH) ? info->v_pos - 1.2 : info->v_out_high;
915   m_v_cc_source = (info->v_cc_source == DEFAULT_555_CC_SOURCE) ? info->v_pos : info->v_cc_source;
916
917   /* Setup based on v_pos power source */
918   m_threshold = info->v_pos * 2.0 / 3.0;
919   m_trigger   = info->v_pos / 3.0;
920
921   m_output_is_ac = info->options & DISC_555_OUT_AC;
922   /* Calculate DC shift needed to make squarewave waveform AC */
923   m_ac_shift     = m_output_is_ac ? -m_v_out_high / 2.0 : 0;
924
925   /* There are 8 different types of basic oscillators
926    * depending on the resistors used.  We will determine
927    * the type of circuit at reset, because the ciruit type
928    * is constant.  See Below.
929    */
930   m_type = (DSD_555_CC__RDIS > 0) | ((DSD_555_CC__RGND  > 0) << 1) | ((DSD_555_CC__RBIAS  > 0) << 2);
931
932   /* optimization if none of the values are nodes */
933   m_has_rc_nodes = 0;
934   if (this->input_is_node() & DSD_555_CC_RC_MASK)
935      m_has_rc_nodes = 1;
936   else
937   {
938      switch (m_type) /* see dsd_555_cc_reset for descriptions */
939      {
940         case 1:
941            r_discharge = DSD_555_CC__RDIS;
942         case 0:
943            break;
944         case 3:
945            r_discharge = RES_2_PARALLEL(DSD_555_CC__RDIS, DSD_555_CC__RGND);
946         case 2:
947            r_charge = DSD_555_CC__RGND;
948            break;
949         case 4:
950            r_charge = DSD_555_CC__RBIAS;
951            break;
952         case 5:
953            r_charge = DSD_555_CC__RBIAS + DSD_555_CC__RDIS;
954            r_discharge = DSD_555_CC__RDIS;
955            break;
956         case 6:
957            r_charge = RES_2_PARALLEL(DSD_555_CC__RBIAS, DSD_555_CC__RGND);
958            break;
959         case 7:
960            r_temp   = DSD_555_CC__RBIAS + DSD_555_CC__RDIS;
961            r_charge = RES_2_PARALLEL(r_temp, DSD_555_CC__RGND);
962            r_discharge = RES_2_PARALLEL(DSD_555_CC__RGND, DSD_555_CC__RDIS);
963            break;
964      }
965
966      m_exp_bleed  = RC_CHARGE_EXP(DSD_555_CC_T_RC_BLEED);
967      m_t_rc_discharge_01 = DSD_555_CC_T_RC_DISCHARGE_01;
968      m_exp_discharge_01  = RC_CHARGE_EXP(m_t_rc_discharge_01);
969      m_t_rc_discharge_no_i = DSD_555_CC_T_RC_DISCHARGE_NO_I;
970      m_exp_discharge_no_i  = RC_CHARGE_EXP(m_t_rc_discharge_no_i);
971      m_t_rc_charge = DSD_555_CC_T_RC_CHARGE;
972      m_exp_charge  = RC_CHARGE_EXP(m_t_rc_charge);
973      m_t_rc_discharge = DSD_555_CC_T_RC_DISCHARGE;
974      m_exp_discharge  = RC_CHARGE_EXP(m_t_rc_discharge);
975   }
976
977   /* Step to set the output */
978   this->step();
979
980   /*
981    * TYPES:
982    * Note: These are equivalent circuits shown without the 555 circuitry.
983    *       See the schematic in src\sound\discrete.h for full hookup info.
984    *
985    * DISCRETE_555_CC_TO_DISCHARGE_PIN
986    * When the CC source is connected to the discharge pin, it allows the
987    * circuit to charge when the 555 is in charge mode.  But when in discharge
988    * mode, the CC source is grounded, disabling it's effect.
989    *
990    * [0]
991    * No resistors.  Straight constant current charge of capacitor.
992    * When there is not any charge current, the cap will bleed off.
993    * Once the lower threshold(trigger) is reached, the output will
994    * go high but the cap will continue to discharge due to losses.
995    *   .------+---> cap_voltage      CHARGING:
996    *   |      |                 dv (change in voltage) compared to dt (change in time in seconds).
997    * .---.   ---                dv = i * dt / C; where i is current in amps and C is capacitance in farads.
998    * | i |   --- C              cap_voltage = cap_voltage + dv
999    * '---'    |
1000    *   |      |               DISCHARGING:
1001    *  gnd    gnd                instantaneous
1002    *
1003    * [1]
1004    * Same as type 1 but with rDischarge.  rDischarge has no effect on the charge rate because
1005    * of the constant current source i.
1006    * When there is not any charge current, the cap will bleed off.
1007    * Once the lower threshold(trigger) is reached, the output will
1008    * go high but the cap will continue to discharge due to losses.
1009    *   .----ZZZ-----+---> cap_voltage      CHARGING:
1010    *   | rDischarge |                 dv (change in voltage) compared to dt (change in time in seconds).
1011    * .---.         ---                dv = i * dt / C; where i is current in amps and C is capacitance in farads.
1012    * | i |         --- C              cap_voltage = cap_voltage + dv
1013    * '---'          |
1014    *   |            |               DISCHARGING:
1015    *  gnd          gnd                through rDischarge
1016    *
1017    * !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
1018    * !!!!! IMPORTANT NOTE ABOUT TYPES 3 - 7 !!!!!
1019    * !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
1020    *
1021    * From here on in all the circuits have either an rBias or rGnd resistor.
1022    * This converts the constant current into a voltage source.
1023    * So all the remaining circuit types will be converted to this circuit.
1024    * When discharging, rBias is out of the equation because the 555 is grounding the circuit
1025    * after that point.
1026    *
1027    * .------------.     Rc                  Rc is the equivilent circuit resistance.
1028    * |     v      |----ZZZZ---+---> cap_voltage    v  is the equivilent circuit voltage.
1029    * |            |           |
1030    * '------------'          ---            Then the standard RC charging formula applies.
1031    *       |                 --- C
1032    *       |                  |             NOTE: All the following types are converted to Rc and v values.
1033    *      gnd                gnd
1034    *
1035    * [2]
1036    * When there is not any charge current, the cap will bleed off.
1037    * Once the lower threshold(trigger) is reached, the output will
1038    * go high but the cap will continue to discharge due to rGnd.
1039    *   .-------+------+------> cap_voltage         CHARGING:
1040    *   |       |      |                       v = vi = i * rGnd
1041    * .---.    ---     Z                       Rc = rGnd
1042    * | i |    --- C   Z rGnd
1043    * '---'     |      |                     DISCHARGING:
1044    *   |       |      |                       instantaneous
1045    *  gnd     gnd    gnd
1046    *
1047    * [3]
1048    * When there is not any charge current, the cap will bleed off.
1049    * Once the lower threshold(trigger) is reached, the output will
1050    * go high but the cap will continue to discharge due to rGnd.
1051    *   .----ZZZ-----+------+------> cap_voltage    CHARGING:
1052    *   | rDischarge |      |                  v = vi = i * rGnd
1053    * .---.         ---     Z                  Rc = rGnd
1054    * | i |         --- C   Z rGnd
1055    * '---'          |      |                DISCHARGING:
1056    *   |            |      |                  through rDischarge || rGnd  ( || means in parallel)
1057    *  gnd          gnd    gnd
1058    *
1059    * [4]
1060    *     .---ZZZ---+------------+-------------> cap_voltage      CHARGING:
1061    *     |  rBias  |            |                           Rc = rBias
1062    * .-------.   .---.         ---                          vi = i * rBias
1063    * | vBias |   | i |         --- C                        v = vBias + vi
1064    * '-------'   '---'          |
1065    *     |         |            |                         DISCHARGING:
1066    *    gnd       gnd          gnd                          instantaneous
1067    *
1068    * [5]
1069    *     .---ZZZ---+----ZZZ-----+-------------> cap_voltage      CHARGING:
1070    *     |  rBias  | rDischarge |                           Rc = rBias + rDischarge
1071    * .-------.   .---.         ---                          vi = i * rBias
1072    * | vBias |   | i |         --- C                        v = vBias + vi
1073    * '-------'   '---'          |
1074    *     |         |            |                         DISCHARGING:
1075    *    gnd       gnd          gnd                          through rDischarge
1076    *
1077    * [6]
1078    *     .---ZZZ---+------------+------+------> cap_voltage      CHARGING:
1079    *     |  rBias  |            |      |                    Rc = rBias || rGnd
1080    * .-------.   .---.         ---     Z                    vi = i * Rc
1081    * | vBias |   | i |         --- C   Z rGnd               v = vBias * (rGnd / (rBias + rGnd)) + vi
1082    * '-------'   '---'          |      |
1083    *     |         |            |      |                  DISCHARGING:
1084    *    gnd       gnd          gnd    gnd                   instantaneous
1085    *
1086    * [7]
1087    *     .---ZZZ---+----ZZZ-----+------+------> cap_voltage      CHARGING:
1088    *     |  rBias  | rDischarge |      |                    Rc = (rBias + rDischarge) || rGnd
1089    * .-------.   .---.         ---     Z                    vi = i * rBias * (rGnd / (rBias + rDischarge + rGnd))
1090    * | vBias |   | i |         --- C   Z rGnd               v = vBias * (rGnd / (rBias + rDischarge + rGnd)) + vi
1091    * '-------'   '---'          |      |
1092    *     |         |            |      |                  DISCHARGING:
1093    *    gnd       gnd          gnd    gnd                   through rDischarge || rGnd
1094    */
1095
1096   /*
1097    * DISCRETE_555_CC_TO_CAP
1098    *
1099    * When the CC source is connected to the capacitor, it allows the
1100    * current to charge the cap while it is in discharge mode, slowing the
1101    * discharge.  So in charge mode it charges linearly from the constant
1102    * current cource.  But when in discharge mode it behaves like circuit
1103    * type 2 above.
1104    *   .-------+------+------> cap_voltage         CHARGING:
1105    *   |       |      |                       dv = i * dt / C
1106    * .---.    ---     Z                       cap_voltage = cap_voltage + dv
1107    * | i |    --- C   Z rDischarge
1108    * '---'     |      |                     DISCHARGING:
1109    *   |       |      |                       v = vi = i * rGnd
1110    *  gnd     gnd   discharge                 Rc = rDischarge
1111    */
1112}
1113
1114
1115/************************************************************************
1116 *
1117 * DSD_555_VCO1 - Usage of node_description values
1118 *
1119 * input[0]    - Reset input value
1120 * input[1]    - Modulation Voltage (Vin1)
1121 * input[2]    - Control Voltage (Vin2)
1122 *
1123 * also passed discrete_5555_vco1_desc structure
1124 *
1125 * Apr 2006, D Renaud.
1126 ************************************************************************/
1127#define DSD_555_VCO1__RESET DISCRETE_INPUT(0)   /* reset active low */
1128#define DSD_555_VCO1__VIN1  DISCRETE_INPUT(1)
1129#define DSD_555_VCO1__VIN2  DISCRETE_INPUT(2)
1130
1131DISCRETE_STEP(dsd_555_vco1)
1132{
1133   DISCRETE_DECLARE_INFO(discrete_555_vco1_desc)
1134
1135   int     count_f = 0;
1136   int     count_r = 0;
1137   double  dt;             /* change in time */
1138   double  x_time  = 0;    /* time since change happened */
1139   double  v_cap;          /* Current voltage on capacitor, before dt */
1140   double  v_cap_next = 0; /* Voltage on capacitor, after dt */
1141
1142   double  v_out = 0;
1143
1144   dt    = this->sample_time();    /* Change in time */
1145   v_cap = m_cap_voltage;
1146
1147   /* Check: if the Control Voltage node is connected. */
1148   if (m_ctrlv_is_node && DSD_555_VCO1__RESET) /* reset active low */
1149   {
1150      /* If CV is less then .25V, the circuit will oscillate way out of range.
1151       * So we will just ignore it when it happens. */
1152      if (DSD_555_VCO1__VIN2 < .25) return;
1153      /* If it is a node then calculate thresholds based on Control Voltage */
1154      m_threshold = DSD_555_VCO1__VIN2;
1155      m_trigger   = DSD_555_VCO1__VIN2 / 2.0;
1156      /* Since the thresholds may have changed we need to update the FF */
1157      if (v_cap >= m_threshold)
1158      {
1159         x_time = dt;
1160         m_flip_flop = 0;
1161         count_f++;
1162      }
1163      else
1164      if (v_cap <= m_trigger)
1165      {
1166         x_time = dt;
1167         m_flip_flop = 1;
1168         count_r++;
1169      }
1170   }
1171
1172   /* Keep looping until all toggling in time sample is used up. */
1173   do
1174   {
1175      if (m_flip_flop)
1176      {
1177         /* if we are in reset then toggle f/f and discharge */
1178         if (!DSD_555_VCO1__RESET)   /* reset active low */
1179         {
1180            m_flip_flop = 0;
1181            count_f++;
1182         }
1183         else
1184         {
1185            /* Charging */
1186            /* iC=C*dv/dt  works out to dv=iC*dt/C */
1187            v_cap_next = v_cap + (m_i_charge * dt / info->c);
1188            dt         = 0;
1189
1190            /* has it charged past upper limit? */
1191            if (v_cap_next >= m_threshold)
1192            {
1193               /* calculate the overshoot time */
1194               dt     = info->c * (v_cap_next - m_threshold) / m_i_charge;
1195               v_cap  = m_threshold;
1196               x_time = dt;
1197               m_flip_flop = 0;
1198               count_f++;
1199            }
1200         }
1201      }
1202      else
1203      {
1204         /* Discharging */
1205         /* iC=C*dv/dt  works out to dv=iC*dt/C */
1206         v_cap_next = v_cap - (m_i_discharge * dt / info->c);
1207
1208         /* if we are in reset, then the cap can discharge to 0 */
1209         if (!DSD_555_VCO1__RESET)   /* reset active low */
1210         {
1211            if (v_cap_next < 0) v_cap_next = 0;
1212            dt = 0;
1213         }
1214         else
1215         {
1216            /* if we are out of reset and the cap voltage is less then
1217             * the lower threshold, toggle f/f and start charging */
1218            if (v_cap <= m_trigger)
1219            {
1220               if (m_flip_flop == 0)
1221               {
1222                  /* don't need to track x_time here */
1223                  m_flip_flop = 1;
1224                  count_r++;
1225               }
1226            }
1227            else
1228            {
1229               dt = 0;
1230               /* has it discharged past lower limit? */
1231               if (v_cap_next <= m_trigger)
1232               {
1233                  /* calculate the overshoot time */
1234                  dt     = info->c * (v_cap_next - m_trigger) / m_i_discharge;
1235                  v_cap  = m_trigger;
1236                  x_time = dt;
1237                  m_flip_flop = 1;
1238                  count_r++;
1239               }
1240            }
1241         }
1242      }
1243   } while(dt);
1244
1245   m_cap_voltage = v_cap_next;
1246
1247   /* Convert last switch time to a ratio.  No x_time in reset. */
1248   x_time = x_time / this->sample_time();
1249   if (!DSD_555_VCO1__RESET) x_time = 0;
1250
1251   switch (m_output_type)
1252   {
1253      case DISC_555_OUT_SQW:
1254         v_out = m_flip_flop * m_v_out_high + m_ac_shift;
1255         break;
1256      case DISC_555_OUT_CAP:
1257         v_out = v_cap_next;
1258         /* Fake it to AC if needed */
1259         if (m_output_is_ac)
1260            v_out -= m_threshold * 3.0 /4.0;
1261         break;
1262      case DISC_555_OUT_ENERGY:
1263         if (x_time == 0) x_time = 1.0;
1264         v_out =  m_v_out_high * (m_flip_flop ? x_time : (1.0 - x_time));
1265         v_out += m_ac_shift;
1266         break;
1267      case DISC_555_OUT_LOGIC_X:
1268         v_out = m_flip_flop + x_time;
1269         break;
1270      case DISC_555_OUT_COUNT_F_X:
1271         v_out = count_f ? count_f + x_time : count_f;
1272         break;
1273      case DISC_555_OUT_COUNT_R_X:
1274         v_out = count_r ? count_r + x_time : count_r;
1275         break;
1276      case DISC_555_OUT_COUNT_F:
1277         v_out = count_f;
1278         break;
1279      case DISC_555_OUT_COUNT_R:
1280         v_out = count_r;
1281         break;
1282   }
1283   set_output(0, v_out);
1284}
1285
1286DISCRETE_RESET(dsd_555_vco1)
1287{
1288   DISCRETE_DECLARE_INFO(discrete_555_vco1_desc)
1289
1290   double v_ratio_r3, v_ratio_r4_1, r_in_1;
1291
1292   m_output_type  = info->options & DISC_555_OUT_MASK;
1293   m_output_is_ac = info->options & DISC_555_OUT_AC;
1294
1295   /* Setup op-amp parameters */
1296
1297   /* The voltage at op-amp +in is always a fixed ratio of the modulation voltage. */
1298   v_ratio_r3 = info->r3 / (info->r2 + info->r3);          /* +in voltage */
1299   /* The voltage at op-amp -in is 1 of 2 fixed ratios of the modulation voltage,
1300    * based on the 555 Flip-Flop state. */
1301   /* If the FF is 0, then only R1 is connected allowing the full modulation volatge to pass. */
1302   /* v_ratio_r4_0 = 1 */
1303   /* If the FF is 1, then R1 & R4 make a voltage divider similar to R2 & R3 */
1304   v_ratio_r4_1 = info->r4 / (info->r1 + info->r4);        /* -in voltage */
1305   /* the input resistance to the op amp depends on the FF state */
1306   /* r_in_0 = info->r1 when FF = 0 */
1307   r_in_1 = 1.0 / (1.0 / info->r1 + 1.0 / info->r4);   /* input resistance when r4 switched in */
1308
1309   /* Now that we know the voltages entering the op amp and the resistance for the
1310    * FF states, we can predetermine the ratios for the charge/discharge currents. */
1311   m_i_discharge = (1 - v_ratio_r3) / info->r1;
1312   m_i_charge    = (v_ratio_r3 - v_ratio_r4_1) / r_in_1;
1313
1314   /* the cap starts off discharged */
1315   m_cap_voltage = 0;
1316
1317   /* Setup 555 parameters */
1318
1319   /* There is no charge on the cap so the 555 goes high at init. */
1320   m_flip_flop     = 1;
1321   m_ctrlv_is_node = (this->input_is_node() >> 2) & 1;
1322   m_v_out_high    = (info->v_out_high == DEFAULT_555_HIGH) ? info->v_pos - 1.2 : info->v_out_high;
1323
1324   /* Calculate 555 thresholds.
1325    * If the Control Voltage is a node, then the thresholds will be calculated each step.
1326    * If the Control Voltage is a fixed voltage, then the thresholds will be calculated
1327    * from that.  Otherwise we will use thresholds based on v_pos. */
1328   if (!m_ctrlv_is_node && (DSD_555_VCO1__VIN2 != -1))
1329   {
1330      /* Setup based on supplied Control Voltage static value */
1331      m_threshold = DSD_555_VCO1__VIN2;
1332      m_trigger   = DSD_555_VCO1__VIN2 / 2.0;
1333   }
1334   else
1335   {
1336      /* Setup based on v_pos power source */
1337      m_threshold = info->v_pos * 2.0 / 3.0;
1338      m_trigger   = info->v_pos / 3.0;
1339   }
1340
1341   /* Calculate DC shift needed to make squarewave waveform AC */
1342   m_ac_shift = m_output_is_ac ? -m_v_out_high / 2.0 : 0;
1343}
1344
1345
1346/************************************************************************
1347 *
1348 * DSD_566 - Usage of node_description values
1349 *
1350 * Mar 2004, D Renaud. updated Sept 2009
1351 *
1352 * The data sheets for this are no where near correct.
1353 * This simulation is based on the internal schematic and testing of
1354 * a real Signetics IC.
1355 *
1356 * The 566 is a constant current based VCO.  If you change R, that affects
1357 * the charge/discharge rate.  A constant current source will charge the
1358 * cap linearly.  Of course due to the transistors there will be some
1359 * non-linear areas at the ends of the Vmod range.  As the Vmod voltage
1360 * drops from Vcharge, the frequency generated increases.
1361 *
1362 * The Triangle (pin 4) output is just a buffered version of the cap
1363 * charge.  It is about 1.35 higher then the cap voltage.
1364 * The Square (pin 3) output starts low as the cap voltages rises.
1365 * Once a threshold is reached, the cap starts to discharge, and the
1366 * Square output goes high.  The Square high output is about 1V less then
1367 * B+.  Unloaded it is .75V less.  With a 4.7k pull-down resistor, it
1368 * is 1.06V less.  So I will simulate at 1V less. The Square low voltage
1369 * is non-linear so I will use a table.  The cap toggle thresholds vary
1370 * depending on B+, so they will be simulated with a table.
1371 *
1372 * The data sheets show Vmod should be no less then 3/4*B+.  In reality
1373 * you can go to close to 1/2*B+ before you lose linearity.  Below 1/2,
1374 * oscillation stops.  When Vmod is 0V to 0.1V less then B+, it also
1375 * loses linearity, and stops oscillating when >= B+.  This is because
1376 * there is no voltage difference to create a current source.
1377 *
1378 * The current source is dependant on the voltage difference between B+
1379 * and Vmod.  Due to transistor action, it is not 100%, but this formula
1380 * gives a good approximation:
1381 * I = ((B+ - Vmod - 0.1) * 0.95) / R
1382 * You can test the current VS modulation function by using 10k for R
1383 * and replace C with a 10k resistor.  Then you can monitor the voltage
1384 * on pin 7 to work out the current.  I=V/R.  It will start to oscillate
1385 * when in the cap threshold range.
1386 *
1387 * When Vmod drops below the stable range, the current source no longer
1388 * functions properly.  Technically this is out of the range specified
1389 * for the IC.  Of course old games used this range anyways, so we need
1390 * to know how the real IC behaves.  When Vmod drops below the stable range,
1391 * the charge current is stops dropping instead of increasing, while the
1392 * discharge current still functions.  This means the frequency generated
1393 * starts to drop as the voltage lowers, instead of the normal increase
1394 * in frequency.
1395 *
1396 ************************************************************************/
1397#define DSD_566__VMOD       DISCRETE_INPUT(0)
1398#define DSD_566__R          DISCRETE_INPUT(1)
1399#define DSD_566__C          DISCRETE_INPUT(2)
1400#define DSD_566__VPOS       DISCRETE_INPUT(3)
1401#define DSD_566__VNEG       DISCRETE_INPUT(4)
1402#define DSD_566__VCHARGE    DISCRETE_INPUT(5)
1403#define DSD_566__OPTIONS    DISCRETE_INPUT(6)
1404
1405
1406static const struct
1407{
1408   double  c_high[6];
1409   double  c_low[6];
1410   double  sqr_low[6];
1411   double  osc_stable[6];
1412   double  osc_stop[6];
1413} ne566 =
1414{
1415   /* 10      10.5      11      11.5      12     13     14     15             B+ */
1416   {3.364, /*3.784,*/ 4.259, /*4.552,*/ 4.888, 5.384, 5.896, 6.416},       /* c_high */
1417   {1.940, /*2.100,*/ 2.276, /*2.404,*/ 2.580, 2.880, 3.180, 3.488},       /* c_low */
1418   {4.352, /*4.144,*/ 4.080, /*4.260,*/ 4.500, 4.960, 5.456, 5.940},       /* sqr_low */
1419   {4.885, /*5.316,*/ 5.772, /*6.075,*/ 6.335, 6.912, 7.492, 7.945},       /* osc_stable */
1420   {4.495, /*4.895,*/ 5.343, /*5.703,*/ 5.997, 6.507, 7.016, 7.518}        /* osc_stop */
1421};
1422
1423DISCRETE_STEP(dsd_566)
1424{
1425   double  i = 0;          /* Charging current created by vIn */
1426   double  i_rise;         /* non-linear rise charge current */
1427   double  dt;             /* change in time */
1428   double  x_time = 0;
1429   double  v_cap;          /* Current voltage on capacitor, before dt */
1430   int     count_f = 0, count_r = 0;
1431
1432   double  v_out = 0.0;
1433
1434   dt    = this->sample_time();    /* Change in time */
1435   v_cap = m_cap_voltage;  /* Set to voltage before change */
1436
1437   /* Calculate charging current if it is in range */
1438   if (EXPECTED(DSD_566__VMOD > m_v_osc_stop))
1439   {
1440      double v_charge = DSD_566__VCHARGE - DSD_566__VMOD - 0.1;
1441      if (v_charge > 0)
1442      {
1443         i = (v_charge * .95) / DSD_566__R;
1444         if (DSD_566__VMOD < m_v_osc_stable)
1445         {
1446            /* no where near correct calculation of non linear range */
1447            i_rise = ((DSD_566__VCHARGE - m_v_osc_stable - 0.1) * .95) / DSD_566__R;
1448            i_rise *= 1.0 - (m_v_osc_stable - DSD_566__VMOD) / (m_v_osc_stable - m_v_osc_stop);
1449         }
1450         else
1451            i_rise = i;
1452      }
1453      else
1454         return;
1455   }
1456   else return;
1457
1458   /* Keep looping until all toggling in this time sample is used up. */
1459   do
1460   {
1461      if (m_flip_flop)
1462      {
1463         /* Discharging */
1464         v_cap -= i * dt / DSD_566__C;
1465         dt     = 0;
1466
1467         /* has it discharged past lower limit? */
1468         if (UNEXPECTED(v_cap < m_threshold_low))
1469         {
1470            /* calculate the overshoot time */
1471            dt = DSD_566__C * (m_threshold_low - v_cap) / i;
1472            v_cap = m_threshold_low;
1473            m_flip_flop = 0;
1474            count_f++;
1475            x_time = dt;
1476         }
1477      }
1478      else
1479      {
1480         /* Charging */
1481         /* iC=C*dv/dt  works out to dv=iC*dt/C */
1482         v_cap += i_rise * dt / DSD_566__C;
1483         dt     = 0;
1484         /* Yes, if the cap voltage has reached the max voltage it can,
1485          * and the 566 threshold has not been reached, then oscillation stops.
1486          * This is the way the actual electronics works.
1487          * This is why you never play with the pots after being factory adjusted
1488          * to work in the proper range. */
1489         if (UNEXPECTED(v_cap > DSD_566__VMOD)) v_cap = DSD_566__VMOD;
1490
1491         /* has it charged past upper limit? */
1492         if (UNEXPECTED(v_cap > m_threshold_high))
1493         {
1494            /* calculate the overshoot time */
1495            dt = DSD_566__C * (v_cap - m_threshold_high) / i;
1496            v_cap = m_threshold_high;
1497            m_flip_flop = 1;
1498            count_r++;
1499            x_time = dt;
1500         }
1501      }
1502   } while(dt);
1503
1504   m_cap_voltage = v_cap;
1505
1506   /* Convert last switch time to a ratio */
1507   x_time /= this->sample_time();
1508
1509   switch (m_out_type)
1510   {
1511      case DISC_566_OUT_SQUARE:
1512         v_out = m_flip_flop ? m_v_sqr_high : m_v_sqr_low;
1513         if (m_fake_ac)
1514            v_out += m_ac_shift;
1515         break;
1516      case DISC_566_OUT_ENERGY:
1517         if (x_time == 0) x_time = 1.0;
1518         v_out = m_v_sqr_low + m_v_sqr_diff * (m_flip_flop ? x_time : (1.0 - x_time));
1519         if (m_fake_ac)
1520            v_out += m_ac_shift;
1521         break;
1522      case DISC_566_OUT_LOGIC:
1523         v_out = m_flip_flop;
1524         break;
1525      case DISC_566_OUT_TRIANGLE:
1526         v_out = v_cap;
1527         if (m_fake_ac)
1528            v_out += m_ac_shift;
1529         break;
1530      case DISC_566_OUT_COUNT_F_X:
1531         v_out = count_f ? count_f + x_time : count_f;
1532         break;
1533      case DISC_566_OUT_COUNT_R_X:
1534         v_out = count_r ? count_r + x_time : count_r;
1535         break;
1536      case DISC_566_OUT_COUNT_F:
1537         v_out = count_f;
1538         break;
1539      case DISC_566_OUT_COUNT_R:
1540         v_out = count_r;
1541         break;
1542   }
1543   set_output(0, v_out);
1544}
1545
1546DISCRETE_RESET(dsd_566)
1547{
1548   int     v_int;
1549   double  v_float;
1550
1551   m_out_type = (int)DSD_566__OPTIONS & DISC_566_OUT_MASK;
1552   m_fake_ac =  (int)DSD_566__OPTIONS & DISC_566_OUT_AC;
1553
1554   if (DSD_566__VNEG >= DSD_566__VPOS)
1555      fatalerror("[v_neg >= v_pos] in NODE_%d!\n", this->index());
1556
1557   v_float = DSD_566__VPOS - DSD_566__VNEG;
1558   v_int = (int)v_float;
1559   if ( v_float < 10 || v_float > 15 )
1560      fatalerror("v_neg and/or v_pos out of range in NODE_%d\n", this->index());
1561   if ( v_float != v_int )
1562      /* fatal for now. */
1563      fatalerror("Power should be integer in NODE_%d\n", this->index());
1564
1565   m_flip_flop   = 0;
1566   m_cap_voltage = 0;
1567
1568   v_int -= 10;
1569   m_threshold_high = ne566.c_high[v_int] + DSD_566__VNEG;
1570   m_threshold_low  = ne566.c_low[v_int] + DSD_566__VNEG;
1571   m_v_sqr_high     = DSD_566__VPOS - 1;
1572   m_v_sqr_low      = ne566.sqr_low[v_int] + DSD_566__VNEG;
1573   m_v_sqr_diff     = m_v_sqr_high - m_v_sqr_low;
1574   m_v_osc_stable  = ne566.osc_stable[v_int] + DSD_566__VNEG;
1575   m_v_osc_stop        = ne566.osc_stop[v_int] + DSD_566__VNEG;
1576
1577   m_ac_shift = 0;
1578   if (m_fake_ac)
1579   {
1580      if (m_out_type == DISC_566_OUT_TRIANGLE)
1581         m_ac_shift = (m_threshold_high - m_threshold_low) / 2 - m_threshold_high;
1582      else
1583         m_ac_shift = m_v_sqr_diff / 2 - m_v_sqr_high;
1584   }
1585
1586   /* Step the output */
1587   this->step();
1588}
1589
1590
1591/************************************************************************
1592 *
1593 * DSD_LS624 - Usage of node_description values
1594 *
1595 * Dec 2007, Couriersud based on data sheet
1596 * Oct 2009, complete re-write based on IC testing
1597 ************************************************************************/
1598#define DSD_LS624__ENABLE       DISCRETE_INPUT(0)
1599#define DSD_LS624__VMOD         DISCRETE_INPUT(1)
1600#define DSD_LS624__VRNG         DISCRETE_INPUT(2)
1601#define DSD_LS624__C            DISCRETE_INPUT(3)
1602#define DSD_LS624__R_FREQ_IN    DISCRETE_INPUT(4)
1603#define DSD_LS624__C_FREQ_IN    DISCRETE_INPUT(5)
1604#define DSD_LS624__R_RNG_IN     DISCRETE_INPUT(6)
1605#define DSD_LS624__OUTTYPE      DISCRETE_INPUT(7)
1606
1607#define LS624_R_EXT         600.0       /* as specified in data sheet */
1608#define LS624_OUT_HIGH      4.5         /* measured */
1609#define LS624_IN_R      RES_K(90)   /* measured & 70K + 20k per data sheet */
1610
1611/*
1612 * The 74LS624 series are constant current based VCOs.  The Freq Control voltage
1613 * modulates the current source.  The current is created from Rext, which is
1614 * internally fixed at 600 ohms for all devices except the 74LS628 which has
1615 * external connections.  The current source linearly discharges the cap voltage.
1616 * The cap starts with 0V charge across it.  One side is connected to a fixed voltage
1617 * bias circuit.  The other side is charged negatively from the current source until
1618 * a certain low threshold is reached.  Once this threshold is reached, the output
1619 * toggles state and the pins on the cap reverse in respect to the charge/bias hookup.
1620 * This starts the one side of the cap to be at bias, and the other side of the cap is
1621 * now at bias + the charge on the cap which is bias - threshold.
1622 * Y = 0;  CX1 = bias;    CX2 = charge
1623 * Y = 1;  CX1 = charge;  CX2 = bias
1624 * The Range voltage adjusts the threshold voltage.  The higher the Range voltage,
1625 * the lower the threshold voltage, the longer the cap can charge, the lower the frequency.
1626 *
1627 * In a perfect world it would work like this:
1628 * The current is based on the mysterious Rext mentioned in the data sheet.
1629 * I = (VfreqControl  * 20k/90k) / Rext
1630 * where Rext = 600 ohms or external Rext on a 74LS628
1631 * The Freq Control has an input impedance of approximately 90k, so any input resistance
1632 * connected to the Freq Control pin works as a voltage divider.
1633 * I = (VfreqControl * 20k/(90k + RfreqControlIn)) / Rext
1634 * That gives us a change in voltage on the cap of
1635 * dV = I / sampleRate / C_inFarads
1636 *
1637 * Unfortunately the chip does not behave linearly do to internal interactions,
1638 * so I have just worked out the formula (using zunzun.com) of FreqControl and
1639 * range to frequency out for a fixed cap value of 0.1uf.  Other cap values can just
1640 * scale from that.  From the freq, we calculate the time of 1/2 cycle using 1/Freq/2.
1641 * Then just use that to toggle a waveform.
1642 */
1643
1644
1645DISCRETE_STEP(dsd_ls624)
1646{
1647   double  x_time = 0;
1648   double  freq, t1;
1649   double  v_freq_2, v_freq_3, v_freq_4;
1650   double  t_used = m_t_used;
1651   double  dt = this->sample_time();;
1652   double  v_freq = DSD_LS624__VMOD;
1653   double  v_rng = DSD_LS624__VRNG;
1654   int     count_f = 0, count_r = 0;
1655
1656   /* coefficients */
1657   const double k1 = 1.9904769024796283E+03;
1658   const double k2 = 1.2070059213983407E+03;
1659   const double k3 = 1.3266985579561108E+03;
1660   const double k4 = -1.5500979825922698E+02;
1661   const double k5 = 2.8184536266938172E+00;
1662   const double k6 = -2.3503421582744556E+02;
1663   const double k7 = -3.3836786704527788E+02;
1664   const double k8 = -1.3569136703258670E+02;
1665   const double k9 = 2.9914575453819188E+00;
1666   const double k10 = 1.6855569086173170E+00;
1667
1668   if (UNEXPECTED(DSD_LS624__ENABLE == 0))
1669      return;
1670
1671   /* scale due to input resistance */
1672   v_freq *= m_v_freq_scale;
1673   v_rng *= m_v_rng_scale;
1674
1675   /* apply cap if needed */
1676   if (m_has_freq_in_cap)
1677   {
1678      m_v_cap_freq_in += (v_freq - m_v_cap_freq_in) * m_exponent;
1679      v_freq = m_v_cap_freq_in;
1680   }
1681
1682   /* Polyfunctional3D_model created by zunzun.com using sum of squared absolute error */
1683   v_freq_2 = v_freq * v_freq;
1684   v_freq_3 = v_freq_2 * v_freq;
1685   v_freq_4 = v_freq_3 * v_freq;
1686   freq = k1;
1687   freq += k2 * v_freq;
1688   freq += k3 * v_freq_2;
1689   freq += k4 * v_freq_3;
1690   freq += k5 * v_freq_4;
1691   freq += k6 * v_rng;
1692   freq += k7 * v_rng * v_freq;
1693   freq += k8 * v_rng * v_freq_2;
1694   freq += k9 * v_rng * v_freq_3;
1695   freq += k10 * v_rng * v_freq_4;
1696
1697   freq *= CAP_U(0.1) / DSD_LS624__C;
1698
1699   t1 = 0.5 / freq ;
1700   t_used += this->sample_time();
1701   do
1702   {
1703      dt = 0;
1704      if (t_used > t1)
1705      {
1706         /* calculate the overshoot time */
1707         t_used -= t1;
1708         m_flip_flop ^= 1;
1709         if (m_flip_flop)
1710            count_r++;
1711         else
1712            count_f++;
1713         /* fix up any frequency increase change errors */
1714         while(t_used > this->sample_time())
1715            t_used -= this->sample_time();
1716         x_time = t_used;
1717         dt = t_used;
1718      }
1719   }while(dt);
1720
1721   m_t_used = t_used;
1722
1723   /* Convert last switch time to a ratio */
1724   x_time = x_time / this->sample_time();
1725
1726   switch (m_out_type)
1727   {
1728      case DISC_LS624_OUT_LOGIC_X:
1729         set_output(0,  m_flip_flop  + x_time);
1730         break;
1731      case DISC_LS624_OUT_COUNT_F_X:
1732         set_output(0,  count_f ? count_f + x_time : count_f);
1733         break;
1734      case DISC_LS624_OUT_COUNT_R_X:
1735         set_output(0,   count_r ? count_r + x_time : count_r);
1736         break;
1737      case DISC_LS624_OUT_COUNT_F:
1738         set_output(0,  count_f);
1739         break;
1740      case DISC_LS624_OUT_COUNT_R:
1741         set_output(0,  count_r);
1742         break;
1743      case DISC_LS624_OUT_ENERGY:
1744         if (x_time == 0) x_time = 1.0;
1745         set_output(0,  LS624_OUT_HIGH * (m_flip_flop ? x_time : (1.0 - x_time)));
1746         break;
1747      case DISC_LS624_OUT_LOGIC:
1748            set_output(0,  m_flip_flop);
1749         break;
1750      case DISC_LS624_OUT_SQUARE:
1751         set_output(0,  m_flip_flop ? LS624_OUT_HIGH : 0);
1752         break;
1753   }
1754}
1755
1756DISCRETE_RESET(dsd_ls624)
1757{
1758   m_out_type = (int)DSD_LS624__OUTTYPE;
1759
1760   m_flip_flop = 0;
1761   m_t_used = 0;
1762   m_v_freq_scale = LS624_IN_R / (DSD_LS624__R_FREQ_IN + LS624_IN_R);
1763   m_v_rng_scale = LS624_IN_R / (DSD_LS624__R_RNG_IN + LS624_IN_R);
1764   if (DSD_LS624__C_FREQ_IN > 0)
1765   {
1766      m_has_freq_in_cap = 1;
1767      m_exponent = RC_CHARGE_EXP(RES_2_PARALLEL(DSD_LS624__R_FREQ_IN, LS624_IN_R) * DSD_LS624__C_FREQ_IN);
1768      m_v_cap_freq_in = 0;
1769   }
1770   else
1771      m_has_freq_in_cap = 0;
1772
1773   set_output(0,  0);
1774}
Property changes on: trunk/src/emu/sound/disc_dev.inc
Added: svn:mime-type
   + text/plain
Added: svn:eol-style
   + native

Previous 199869 Revisions Next


© 1997-2024 The MAME Team