469
503
node->output[0] = 0;
470
504
context->flip_flop = 0;
471
505
context->cap_voltage = 0;
477
if (context->trig_is_logic)
478
trigger = !DSD_555_MSTBL__TRIGGER;
480
trigger = DSD_555_MSTBL__TRIGGER < context->trigger;
482
if (context->trig_discharges_cap && trigger)
509
trigger_type = info->options;
510
dt = node->info->sample_time;
512
switch (trigger_type & DSD_555_TRIGGER_TYPE_MASK)
514
case DISC_555_TRIGGER_IS_LOGIC:
515
trigger = (int)!DSD_555_MSTBL__TRIGGER;
517
case DISC_555_TRIGGER_IS_VOLTAGE:
518
trigger = (int)(DSD_555_MSTBL__TRIGGER < context->trigger);
520
case DISC_555_TRIGGER_IS_COUNT:
521
trigger = (int)DSD_555_MSTBL__TRIGGER;
522
if (trigger && !context->flip_flop)
524
x_time = DSD_555_MSTBL__TRIGGER - trigger;
527
/* adjust sample to after trigger */
528
x_time = (1.0 - x_time);
530
dt = x_time * node->info->sample_time;
536
if ((trigger_type & DISC_555_TRIGGER_DISCHARGES_CAP) && trigger)
537
context->cap_voltage = 0;
539
/* Wait for trigger */
540
if (!context->flip_flop && trigger)
541
context->flip_flop = 1;
543
if (context->flip_flop)
545
v_cap = context->cap_voltage;
547
/* Sometimes a switching network is used to setup the capacitance.
548
* These may select 'no' capacitor, causing oscillation to stop.
550
if (DSD_555_MSTBL__C == 0)
552
context->flip_flop = 0;
553
/* The voltage goes high because the cap circuit is open. */
554
v_cap_next = info->v_pos;
483
556
context->cap_voltage = 0;
485
if (!context->flip_flop)
487
/* Wait for trigger */
489
context->flip_flop = 1;
493
v_cap = context->cap_voltage;
561
update_exponent |= context->has_rc_nodes;
563
exponent = RC_CHARGE_EXP_DT(DSD_555_MSTBL__R * DSD_555_MSTBL__C, dt);
565
exponent = context->exp_charge;
566
v_cap_next = v_cap + ((info->v_pos - v_cap) * exponent);
495
/* Sometimes a switching network is used to setup the capacitance.
496
* These may select 'no' capacitor, causing oscillation to stop.
498
if (DSD_555_MSTBL__C == 0)
568
/* Has it charged past upper limit? */
569
/* If trigger is still enabled, then we keep charging,
570
* regardless of threshold. */
571
if ((v_cap_next >= context->threshold) && !trigger)
573
dt = DSD_555_MSTBL__R * DSD_555_MSTBL__C * log(1.0 / (1.0 - ((v_cap_next - context->threshold) / (context->v_charge - v_cap))));
574
x_time = dt / node->info->sample_time;
576
v_cap = context->threshold;
500
577
context->flip_flop = 0;
501
/* The voltage goes high because the cap circuit is open. */
502
v_cap_next = info->v_pos;
504
context->cap_voltage = 0;
509
v_cap_next = v_cap + ((info->v_pos - v_cap) * RC_CHARGE_EXP(DSD_555_MSTBL__R * DSD_555_MSTBL__C));
511
/* Has it charged past upper limit? */
512
/* If trigger is still enabled, then we keep charging,
513
* regardless of threshold. */
514
if ((v_cap_next >= context->threshold) && !trigger)
517
v_cap = context->threshold;
518
context->flip_flop = 0;
522
context->cap_voltage = v_cap_next;
524
switch (info->options & DISC_555_OUT_MASK)
526
case DISC_555_OUT_SQW:
527
node->output[0] = context->flip_flop * context->v_out_high;
528
/* Fake it to AC if needed */
529
if (context->output_is_ac)
530
node->output[0] -= context->v_out_high / 2.0;
532
case DISC_555_OUT_CAP:
533
node->output[0] = v_cap_next;
534
/* Fake it to AC if needed */
535
if (context->output_is_ac)
536
node->output[0] -= context->threshold * 3.0 /4.0;
581
context->cap_voltage = v_cap_next;
584
switch (info->options & DISC_555_OUT_MASK)
586
case DISC_555_OUT_SQW:
587
node->output[0] = context->flip_flop * context->v_out_high;
588
/* Fake it to AC if needed */
589
if (context->output_is_ac)
590
node->output[0] -= context->v_out_high / 2.0;
592
case DISC_555_OUT_CAP:
593
node->output[0] = v_cap_next;
594
/* Fake it to AC if needed */
595
if (context->output_is_ac)
596
node->output[0] -= context->threshold * 3.0 /4.0;
598
case DISC_555_OUT_ENERGY:
599
if (x_time == 0) x_time = 1.0;
600
node->output[0] = context->v_out_high * (context->flip_flop ? x_time : (1.0 - x_time));
601
if (context->output_is_ac)
602
node->output[0] -= context->v_out_high / 2.0;
1372
1444
context->ac_shift = context->output_is_ac ? -context->v_out_high / 2.0 : 0;
1375
1448
/************************************************************************
1377
1450
* DSD_566 - Usage of node_description values
1379
* input[0] - Enable input value
1380
* input[1] - Modulation Voltage
1381
* input[2] - R value
1382
* input[3] - C value
1384
* also passed discrete_566_desc structure
1386
* Mar 2004, D Renaud.
1452
* Mar 2004, D Renaud. updated Sept 2009
1454
* The data sheets for this are no where near correct.
1455
* This simulation is based on the internal schematic and testing of
1456
* a real Signetics IC.
1458
* The 566 is a constant current based VCO. If you change R, that affects
1459
* the charge/discharge rate. A constant current source will charge the
1460
* cap linearly. Of course due to the transistors there will be some
1461
* non-linear areas at the ends of the Vmod range. As the Vmod voltage
1462
* drops from Vcharge, the frequency generated increases.
1464
* The Triangle (pin 4) output is just a buffered version of the cap
1465
* charge. It is about 1.35 higher then the cap voltage.
1466
* The Square (pin 3) output starts low as the cap voltages rises.
1467
* Once a threshold is reached, the cap starts to discharge, and the
1468
* Square output goes high. The Square high output is about 1V less then
1469
* B+. Unloaded it is .75V less. With a 4.7k pull-down resistor, it
1470
* is 1.06V less. So I will simulate at 1V less. The Square low voltage
1471
* is non-linear so I will use a table. The cap toggle thresholds vary
1472
* depending on B+, so they will be simulated with a table.
1474
* The data sheets show Vmod should be no less then 3/4*B+. In reality
1475
* you can go to close to 1/2*B+ before you loose linearity. Below 1/2,
1476
* oscillation stops. When Vmod is 0V to 0.1V less then B+, it also
1477
* looses linearity, and stops oscillating when >= B+. This is because
1478
* there is no voltage difference to create a current source.
1480
* The current source is dependant on the voltage difference between B+
1481
* and Vmod. Due to transistor action, it is not 100%, but this formula
1482
* gives a good approximation:
1483
* I = ((B+ - Vmod - 0.1) * 0.95) / R
1484
* You can test the current VS modulation function by using 10k for R
1485
* and replace C with a 10k resistor. Then you can monitor the voltage
1486
* on pin 7 to work out the current. I=V/R. It will start to oscillate
1487
* when in the cap threshold range.
1489
* When Vmod drops below the stable range, the current source no longer
1490
* functions properly. Technically this is out of the range specified
1491
* for the IC. Of course old games used this range anyways, so we need
1492
* to know how the real IC behaves. When Vmod drops below the stable range,
1493
* the charge current is stops dropping instead of increasing, while the
1494
* discharge current still functions. This means the frequency generated
1495
* starts to drop as the voltage lowers, instead of the normal increase
1387
1498
************************************************************************/
1388
#define DSD_566__ENABLE (*(node->input[0]))
1389
#define DSD_566__VMOD (*(node->input[1]))
1390
#define DSD_566__R (*(node->input[2]))
1391
#define DSD_566__C (*(node->input[3]))
1499
#define DSD_566__VMOD DISCRETE_INPUT(0)
1500
#define DSD_566__R DISCRETE_INPUT(1)
1501
#define DSD_566__C DISCRETE_INPUT(2)
1502
#define DSD_566__VPOS DISCRETE_INPUT(3)
1503
#define DSD_566__VNEG DISCRETE_INPUT(4)
1504
#define DSD_566__VCHARGE DISCRETE_INPUT(5)
1505
#define DSD_566__OPTIONS DISCRETE_INPUT(6)
1513
double osc_stable[6];
1517
/* 10 10.5 11 11.5 12 13 14 15 B+ */
1518
{3.364, /*3.784,*/ 4.259, /*4.552,*/ 4.888, 5.384, 5.896, 6.416}, /* c_high */
1519
{1.940, /*2.100,*/ 2.276, /*2.404,*/ 2.580, 2.880, 3.180, 3.488}, /* c_low */
1520
{4.352, /*4.144,*/ 4.080, /*4.260,*/ 4.500, 4.960, 5.456, 5.940}, /* sqr_low */
1521
{4.885, /*5.316,*/ 5.772, /*6.075,*/ 6.335, 6.912, 7.492, 7.945}, /* osc_stable */
1522
{4.495, /*4.895,*/ 5.343, /*5.703,*/ 5.997, 6.507, 7.016, 7.518} /* osc_stop */
1393
1525
static DISCRETE_STEP(dsd_566)
1395
const discrete_566_desc *info = (const discrete_566_desc *)node->custom;
1396
1527
struct dsd_566_context *context = (struct dsd_566_context *)node->context;
1398
double i; /* Charging current created by vIn */
1399
double dt; /* change in time */
1400
double v_cap; /* Current voltage on capacitor, before dt */
1401
double v_cap_next = 0; /* Voltage on capacitor, after dt */
1404
if (DSD_566__ENABLE && !context->error)
1529
double i = 0; /* Charging current created by vIn */
1530
double i_rise; /* non-linear rise charge current */
1531
double dt; /* change in time */
1533
double v_cap; /* Current voltage on capacitor, before dt */
1534
int count_f = 0, count_r = 0;
1536
dt = node->info->sample_time; /* Change in time */
1537
v_cap = context->cap_voltage; /* Set to voltage before change */
1539
/* Calculate charging current if it is in range */
1540
if (EXPECTED(DSD_566__VMOD > context->v_osc_stop))
1406
dt = discrete_current_context->sample_time; /* Change in time */
1407
v_cap = context->cap_voltage; /* Set to voltage before change */
1409
/* get the v_charge and update each step if it is a node */
1410
if (context->v_charge_node != NULL)
1412
v_charge = *context->v_charge_node;
1413
v_charge -= info->v_neg;
1416
v_charge = context->v_charge;
1418
/* Calculate charging current */
1419
i = (v_charge - DSD_566__VMOD) / DSD_566__R;
1421
/* Keep looping until all toggling in time sample is used up. */
1424
if (context->flip_flop)
1542
double v_charge = DSD_566__VCHARGE - DSD_566__VMOD - 0.1;
1545
i = (v_charge * .95) / DSD_566__R;
1546
if (DSD_566__VMOD < context->v_osc_stable)
1427
v_cap_next = v_cap - (i * dt / DSD_566__C);
1430
/* has it discharged past lower limit? */
1431
if (v_cap_next <= context->threshold_low)
1433
if (v_cap_next < context->threshold_low)
1435
/* calculate the overshoot time */
1436
dt = DSD_566__C * (context->threshold_low - v_cap_next) / i;
1438
v_cap = context->threshold_low;
1439
context->flip_flop = 0;
1441
* If the sampling rate is too low and the desired frequency is too high
1442
* then we will start getting too many outputs that can't catch up. We will
1443
* limit this to 3. The output is already incorrect because of the low sampling,
1444
* but at least this way it can recover.
1446
context->state[0] = (context->state[0] + 1) & 0x03;
1548
/* no where near correct calculation of non linear range */
1549
i_rise = ((DSD_566__VCHARGE - context->v_osc_stable - 0.1) * .95) / DSD_566__R;
1550
i_rise *= 1.0 - (context->v_osc_stable - DSD_566__VMOD) / (context->v_osc_stable - context->v_osc_stop);
1452
/* iC=C*dv/dt works out to dv=iC*dt/C */
1453
v_cap_next = v_cap + (i * dt / DSD_566__C);
1455
/* Yes, if the cap voltage has reached the max voltage it can,
1456
* and the 566 threshold has not been reached, then oscillation stops.
1457
* This is the way the actual electronics works.
1458
* This is why you never play with the pots after being factory adjusted
1459
* to work in the proper range. */
1460
if (v_cap_next > DSD_566__VMOD) v_cap_next = DSD_566__VMOD;
1462
/* has it charged past upper limit? */
1463
if (v_cap_next >= context->threshold_high)
1465
if (v_cap_next > context->threshold_high)
1467
/* calculate the overshoot time */
1468
dt = DSD_566__C * (v_cap_next - context->threshold_high) / i;
1470
v_cap = context->threshold_high;
1471
context->flip_flop = 1;
1472
context->state[1] = (context->state[1] + 1) & 0x03;
1477
context->cap_voltage = v_cap_next;
1479
switch (info->options & DISC_566_OUT_MASK)
1481
case DISC_566_OUT_SQUARE:
1482
case DISC_566_OUT_LOGIC:
1483
/* use up any output states */
1484
if (node->output[0] && context->state[0])
1486
node->output[0] = 0;
1487
context->state[0]--;
1489
else if (!node->output[0] && context->state[1])
1491
node->output[0] = 1;
1492
context->state[1]--;
1496
node->output[0] = context->flip_flop;
1498
if ((info->options & DISC_566_OUT_MASK) != DISC_566_OUT_LOGIC)
1499
node->output[0] = context->flip_flop ? context->v_sqr_high : context->v_sqr_low;
1501
case DISC_566_OUT_TRIANGLE:
1502
/* we can ignore any unused states when
1503
* outputting the cap voltage */
1504
node->output[0] = v_cap_next;
1505
if (info->options & DISC_566_OUT_AC)
1506
node->output[0] -= context->triangle_ac_offset;
1511
node->output[0] = 0;
1560
/* Keep looping until all toggling in this time sample is used up. */
1563
if (context->flip_flop)
1566
v_cap -= i * dt / DSD_566__C;
1569
/* has it discharged past lower limit? */
1570
if (UNEXPECTED(v_cap < context->threshold_low))
1572
/* calculate the overshoot time */
1573
dt = DSD_566__C * (context->threshold_low - v_cap) / i;
1574
v_cap = context->threshold_low;
1575
context->flip_flop = 0;
1583
/* iC=C*dv/dt works out to dv=iC*dt/C */
1584
v_cap += i_rise * dt / DSD_566__C;
1586
/* Yes, if the cap voltage has reached the max voltage it can,
1587
* and the 566 threshold has not been reached, then oscillation stops.
1588
* This is the way the actual electronics works.
1589
* This is why you never play with the pots after being factory adjusted
1590
* to work in the proper range. */
1591
if (UNEXPECTED(v_cap > DSD_566__VMOD)) v_cap = DSD_566__VMOD;
1593
/* has it charged past upper limit? */
1594
if (UNEXPECTED(v_cap > context->threshold_high))
1596
/* calculate the overshoot time */
1597
dt = DSD_566__C * (v_cap - context->threshold_high) / i;
1598
v_cap = context->threshold_high;
1599
context->flip_flop = 1;
1606
context->cap_voltage = v_cap;
1608
/* Convert last switch time to a ratio */
1609
x_time /= node->info->sample_time;
1611
switch (context->out_type)
1613
case DISC_566_OUT_SQUARE:
1614
node->output[0] = context->flip_flop ? context->v_sqr_high : context->v_sqr_low;
1615
if (context->fake_ac)
1616
node->output[0] += context->ac_shift;
1618
case DISC_566_OUT_ENERGY:
1619
if (x_time == 0) x_time = 1.0;
1620
node->output[0] = context->v_sqr_low + context->v_sqr_diff * (context->flip_flop ? x_time : (1.0 - x_time));
1621
if (context->fake_ac)
1622
node->output[0] += context->ac_shift;
1624
case DISC_566_OUT_LOGIC:
1625
node->output[0] = context->flip_flop;
1627
case DISC_566_OUT_TRIANGLE:
1628
node->output[0] = v_cap;
1629
if (context->fake_ac)
1630
node->output[0] += context->ac_shift;
1632
case DISC_566_OUT_COUNT_F_X:
1633
node->output[0] = count_f ? count_f + x_time : count_f;
1635
case DISC_566_OUT_COUNT_R_X:
1636
node->output[0] = count_r ? count_r + x_time : count_r;
1638
case DISC_566_OUT_COUNT_F:
1639
node->output[0] = count_f;
1641
case DISC_566_OUT_COUNT_R:
1642
node->output[0] = count_r;
1514
1647
static DISCRETE_RESET(dsd_566)
1516
const discrete_566_desc *info = (const discrete_566_desc *)node->custom;
1517
1649
struct dsd_566_context *context = (struct dsd_566_context *)node->context;
1518
node_description *v_charge_node;
1520
double v_diff, temp;
1523
if (info->v_neg >= info->v_pos)
1525
logerror("[v_neg >= v_pos] - NODE_%d DISABLED!\n", node->node - NODE_00);
1530
/* setup v_charge or node */
1531
v_charge_node = discrete_find_node(NULL, info->v_charge);
1533
context->v_charge_node = &(v_charge_node->output[NODE_CHILD_NODE_NUM(info->v_charge)]);
1536
context->v_charge = (info->v_charge == DEFAULT_566_CHARGE) ? info->v_pos : info->v_charge;
1537
context->v_charge -= info->v_neg;
1538
context->v_charge_node = NULL;
1541
v_diff = info->v_pos - info->v_neg;
1654
context->out_type = (int)DSD_566__OPTIONS & DISC_566_OUT_MASK;
1655
context->fake_ac = (int)DSD_566__OPTIONS & DISC_566_OUT_AC;
1657
if (DSD_566__VNEG >= DSD_566__VPOS)
1658
fatalerror("[v_neg >= v_pos] in NODE_%d!\n", NODE_BLOCKINDEX(node));
1660
v_float = DSD_566__VPOS - DSD_566__VNEG;
1661
v_int = (int)v_float;
1662
if ( v_float < 10 || v_float > 15 )
1663
fatalerror("v_neg and/or v_pos out of range in NODE_%d\n", NODE_BLOCKINDEX(node));
1664
if ( v_float != v_int )
1665
/* fatal for now. */
1666
fatalerror("Power should be integer in NODE_%d\n", NODE_BLOCKINDEX(node));
1542
1668
context->flip_flop = 0;
1543
1669
context->cap_voltage = 0;
1544
context->state[0] = 0;
1545
context->state[1] = 0;
1547
/* The data sheets are useless for this IC. I will have to get my hands on a chip
1548
* to make real measurements. For now this should work fine for 12V. */
1549
context->threshold_high = v_diff / 2 + info->v_neg;
1550
context->threshold_low = context->threshold_high - (0.2 * v_diff);
1551
context->v_sqr_high = info->v_pos - 0.6;
1552
context->v_sqr_low = context->threshold_high;
1554
if (info->options & DISC_566_OUT_AC)
1672
context->threshold_high = ne566.c_high[v_int] + DSD_566__VNEG;
1673
context->threshold_low = ne566.c_low[v_int] + DSD_566__VNEG;
1674
context->v_sqr_high = DSD_566__VPOS - 1;
1675
context->v_sqr_low = ne566.sqr_low[v_int] + DSD_566__VNEG;
1676
context->v_sqr_diff = context->v_sqr_high - context->v_sqr_low;
1677
context->v_osc_stable = ne566.osc_stable[v_int] + DSD_566__VNEG;
1678
context->v_osc_stop = ne566.osc_stop[v_int] + DSD_566__VNEG;
1680
context->ac_shift = 0;
1681
if (context->fake_ac)
1556
temp = (context->v_sqr_high - context->v_sqr_low) / 2;
1557
context->v_sqr_high = temp;
1558
context->v_sqr_low = -temp;
1559
context->triangle_ac_offset = context->threshold_high - (0.1 * v_diff);
1683
if (context->out_type == DISC_566_OUT_TRIANGLE)
1684
context->ac_shift = (context->threshold_high - context->threshold_low) / 2 - context->threshold_high;
1686
context->ac_shift = context->v_sqr_diff / 2 - context->v_sqr_high;
1562
1689
/* Step the output */
1563
1690
DISCRETE_STEP_CALL(dsd_566);
1566
1694
/************************************************************************
1568
1696
* DSD_LS624 - Usage of node_description values
1570
* input[0] - Enable input value
1571
* input[1] - Modulation Voltage
1572
* input[2] - Range Voltage
1573
* input[3] - C value
1574
* input[4] - Output type
1698
* input[0] - Modulation Voltage
1699
* input[1] - Range Voltage
1700
* input[2] - C value
1701
* input[3] - Output type
1576
1703
* Dec 2007, Couriersud
1577
1704
************************************************************************/
1578
#define DSD_LS624__ENABLE (*(node->input[0]))
1579
#define DSD_LS624__VMOD (*(node->input[1]))
1580
#define DSD_LS624__VRNG (*(node->input[2]))
1581
#define DSD_LS624__C (*(node->input[3]))
1582
#define DSD_LS624__OUTTYPE (*(node->input[4]))
1705
#define DSD_LS624__VMOD DISCRETE_INPUT(0)
1706
#define DSD_LS624__VRNG DISCRETE_INPUT(1)
1707
#define DSD_LS624__C DISCRETE_INPUT(2)
1708
#define DSD_LS624__OUTTYPE DISCRETE_INPUT(3)
1585
1711
* The datasheet mentions a 600 ohm discharge. It also gives
1593
1719
* where calculated using least square approximation.
1594
1720
* This approach gives a bit better results compared to the first approach.
1596
#define LS624_F(_C, _VI, _VR) pow(10, -0.912029404 * log10(_C) + 0.243264328 * (_VI) \
1597
- 0.091695877 * (_VR) -0.014110946 * (_VI) * (_VR) - 3.207072925)
1722
/* Original formula before optimization of static values
1723
#define LS624_F(_C, _VI, _VR) pow(10, -0.912029404 * log10(_C) + 0.243264328 * (_VI) \
1724
- 0.091695877 * (_VR) -0.014110946 * (_VI) * (_VR) - 3.207072925)
1727
/* pow(10, x) = exp(ln(10)*x) */
1728
#define pow10(x) exp(2.30258509299404568401*(x))
1730
#define LS624_F(_VI) pow10(context->k1 + 0.243264328 * (_VI) + context->k2 * (_VI))
1599
1732
static DISCRETE_STEP(dsd_ls624)
1601
1734
struct dsd_ls624_context *context = (struct dsd_ls624_context *)node->context;
1603
if (DSD_LS624__ENABLE)
1605
double dt; /* change in time */
1609
int cntf = 0, cntr = 0;
1611
sample_t = discrete_current_context->sample_time; /* Change in time */
1612
//dt = LS624_T(DSD_LS624__C, DSD_LS624__VRNG, DSD_LS624__VMOD) / 2.0;
1613
dt = 1.0f / (2.0f * LS624_F(DSD_LS624__C, DSD_LS624__VMOD, DSD_LS624__VRNG));
1614
t = context->remain;
1615
en += (double) context->state * t;
1616
while (t + dt <= sample_t)
1618
en += (double) context->state * dt;
1619
context->state = (1 - context->state);
1736
double dt; /* change in time */
1740
int cntf = 0, cntr = 0;
1742
sample_t = node->info->sample_time; /* Change in time */
1743
//dt = LS624_T(DSD_LS624__C, DSD_LS624__VRNG, DSD_LS624__VMOD) / 2.0;
1744
if (EXPECTED(DSD_LS624__VMOD > 0.001))
1745
dt = 0.5 / LS624_F(DSD_LS624__VMOD);
1747
/* close enough to 0, so we can speed things up by no longer call pow() */
1748
dt = context->dt_vmod_at_0;
1749
t = context->remain;
1750
en += (double) context->state * t;
1751
while (EXPECTED(t + dt <= sample_t))
1753
en += (double) context->state * dt;
1754
context->state = (1 - context->state);
1761
en += (sample_t - t) * (double) context->state;
1762
context->remain = t - sample_t;
1764
switch (context->out_type)
1766
case DISC_LS624_OUT_ENERGY:
1767
node->output[0] = en / sample_t;
1769
case DISC_LS624_OUT_LOGIC:
1770
/* filter out randomness */
1771
if (UNEXPECTED(cntf + cntr > 1))
1772
node->output[0] = 1;
1626
en += (sample_t - t) * (double) context->state;
1627
context->remain = t - sample_t;
1629
switch (context->out_type)
1631
case DISC_LS624_OUT_ENERGY:
1632
node->output[0] = en / sample_t;
1634
case DISC_LS624_OUT_LOGIC:
1635
/* filter out randomness */
1636
if (cntf + cntr > 1)
1637
node->output[0] = 1;
1639
node->output[0] = context->state;
1641
case DISC_LS624_OUT_COUNT_F:
1642
node->output[0] = cntf;
1644
case DISC_LS624_OUT_COUNT_R:
1645
node->output[0] = cntr;
1774
node->output[0] = context->state;
1776
case DISC_LS624_OUT_COUNT_F:
1777
node->output[0] = cntf;
1779
case DISC_LS624_OUT_COUNT_R:
1780
node->output[0] = cntr;
1651
node->output[0] = 0;
1654
1785
static DISCRETE_RESET(dsd_ls624)
1659
1790
context->state = 0;
1660
1791
context->out_type = DSD_LS624__OUTTYPE;
1793
/* precalculate some parts of the formula for speed */
1794
context->k1 = -0.912029404 * log10(DSD_LS624__C) -0.091695877 * (DSD_LS624__VRNG) - 3.207072925;
1795
context->k2 = -0.014110946 * (DSD_LS624__VRNG);
1797
context->dt_vmod_at_0 = 0.5 / LS624_F(0);
1662
1799
/* Step the output */
1663
1800
DISCRETE_STEP_CALL(dsd_ls624);
1804
/************************************************************************
1806
* DSD_LS629 - Usage of node_description values
1808
* Dec 2007, Couriersud based on data sheet
1809
* Oct 2009, complete re-write based on IC testing
1810
************************************************************************/
1811
#define DSD_LS629__ENABLE DISCRETE_INPUT(0)
1812
#define DSD_LS629__VMOD DISCRETE_INPUT(1)
1813
#define DSD_LS629__VRNG DISCRETE_INPUT(2)
1814
#define DSD_LS629__C DISCRETE_INPUT(3)
1815
#define DSD_LS629__R_FREQ_IN DISCRETE_INPUT(4)
1816
#define DSD_LS629__OUTTYPE DISCRETE_INPUT(5)
1818
#define LS624_R_EXT 600.0 /* as specified in data sheet */
1819
#define LS624_OUT_HIGH 4.5 /* measured */
1820
#define LS624_FREQ_R_IN RES_K(95) /* measured */
1823
* The 74LS624 series are constant current based VCOs. The Freq Control voltage
1824
* modulates the current source. The current is created from Rext, which is
1825
* internally fixed at 600 ohms for all devices except the 74LS628 which has
1826
* external connections. The current source linearly discharges the cap voltage.
1827
* The cap starts with 0V charge across it. One side is connected to a fixed voltage
1828
* bias circuit. The other side is charged negatively from the current source until
1829
* a certain low threshold is reached. Once this threshold is reached, the output
1830
* toggles state and the pins on the cap reverse in respect to the charge/bias hookup.
1831
* This starts the one side of the cap to be at bias, and the other side of the cap is
1832
* now at bias + the charge on the cap which is bias - threshold.
1833
* Y = 0; CX1 = bias; CX2 = charge
1834
* Y = 1; CX1 = charge; CX2 = bias
1835
* The Range voltage adjusts the threshold voltage. The higher the Range voltage,
1836
* the lower the threshold voltage, the longer the cap can charge, the lower the frequency.
1838
* The current is based on the mysterious Rext mentioned in the data sheet.
1839
* I = (VfreqControl / 5) / Rext
1840
* where Rext = 600 ohms or external Rext on a 74LS628
1841
* The Freq Control has an input impedance of approximately 100k, so any input resistance
1842
* connected to the Freq Control pin works as a voltage divider.
1843
* I = (VfreqControl / 5 * 100000 / (RfreqControl + 100000)) / Rext
1844
* That gives us a change in voltage on the cap of
1845
* dV = I / sampleRate / C_inFarads
1848
/* The range to bias and threshold routines were created from testing a real chip.
1849
* This data was entered into the function finder routine at www.zunzun.com
1850
* to create the following 2 routines
1853
double range_to_bias(double range)
1855
/* Quadratic2D_model */
1859
const double a = 2.3107142857142846E+00;
1860
const double b = -1.0714285714278806E-03;
1861
const double c = -1.7857142857144002E-03;
1865
bias += c * pow(range, 2.0);
1869
double range_to_threshold(double range)
1871
/* Polyfunctional2D_model */
1875
const double a = -1.6124587587173614E-01;
1876
const double b = -1.3501987413150401E-01;
1877
const double offset = 2.2550390868489893E+00;
1879
threshold = a * range;
1880
threshold += b * exp(-1.0 * range);
1881
threshold += offset;
1886
static DISCRETE_STEP(dsd_ls629)
1888
struct dsd_ls629_context *context = (struct dsd_ls629_context *)node->context;
1890
double i; /* Charging current created by Freq Control */
1891
double dt; /* change in time */
1893
double v_cap; /* Current voltage on capacitor, before dt */
1894
int count_f = 0, count_r = 0;
1896
if (UNEXPECTED(DSD_LS629__ENABLE == 0))
1899
dt = node->info->sample_time; /* Change in time */
1900
v_cap = context->v_cap; /* Set to voltage before change */
1903
/* Calculate charging current */
1904
i = DSD_LS629__VMOD * context->k_vmod_to_i;
1906
/* Keep looping until all toggling in this time sample is used up. */
1909
/* Always Discharging */
1910
v_cap -= i * dt / DSD_LS629__C;
1913
/* has it discharged past lower limit? */
1914
if (UNEXPECTED(v_cap < context->v_threshold))
1916
/* calculate the overshoot time */
1917
dt = DSD_LS629__C * (context->v_threshold - v_cap) / i;
1918
v_cap = context->v_peak;
1919
context->flip_flop ^= 1;
1920
if (context->flip_flop)
1928
context->v_cap = v_cap;
1930
/* Convert last switch time to a ratio */
1931
x_time = x_time / node->info->sample_time;
1933
switch (context->out_type)
1935
case DISC_LS624_OUT_SQUARE:
1936
node->output[0] = context->flip_flop ? LS624_OUT_HIGH : 0;
1938
case DISC_LS624_OUT_ENERGY:
1939
if (x_time == 0) x_time = 1.0;
1940
node->output[0] = LS624_OUT_HIGH * (context->flip_flop ? x_time : (1.0 - x_time));
1942
case DISC_LS624_OUT_LOGIC:
1943
node->output[0] = context->flip_flop;
1945
case DISC_LS624_OUT_COUNT_F_X:
1946
node->output[0] = count_f ? count_f + x_time : count_f;
1948
case DISC_LS624_OUT_COUNT_R_X:
1949
node->output[0] = count_r ? count_r + x_time : count_r;
1951
case DISC_LS624_OUT_COUNT_F:
1952
node->output[0] = count_f;
1954
case DISC_LS624_OUT_COUNT_R:
1955
node->output[0] = count_r;
1960
#define LS624_LOSS_FACTOR 0.92
1962
static DISCRETE_RESET(dsd_ls629)
1964
struct dsd_ls629_context *context = (struct dsd_ls629_context *)node->context;
1966
context->out_type = (int)DSD_LS629__OUTTYPE;
1968
context->v_bias = range_to_bias(DSD_LS629__VRNG);
1969
context->v_cap = context->v_bias;
1970
context->v_threshold = range_to_threshold(DSD_LS629__VRNG);
1971
/* The voltage at the current charge pin after a state change */
1972
context->v_peak = context->v_bias * 2 - context->v_threshold;
1973
context->flip_flop = 0;
1974
/* precalulate the voltage to current formula */
1975
context->k_vmod_to_i = 1.0 / 5 * LS624_FREQ_R_IN / (DSD_LS629__R_FREQ_IN + LS624_FREQ_R_IN) / LS624_R_EXT;
1976
context->k_vmod_to_i *= LS624_LOSS_FACTOR;
1978
node->output[0] = 0;