summaryrefslogtreecommitdiffstatshomepage
path: root/src/lib/netlist/devices/nld_74ls629.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/lib/netlist/devices/nld_74ls629.cpp')
-rw-r--r--src/lib/netlist/devices/nld_74ls629.cpp282
1 files changed, 124 insertions, 158 deletions
diff --git a/src/lib/netlist/devices/nld_74ls629.cpp b/src/lib/netlist/devices/nld_74ls629.cpp
index 20798f7da69..11cbc8aeb0d 100644
--- a/src/lib/netlist/devices/nld_74ls629.cpp
+++ b/src/lib/netlist/devices/nld_74ls629.cpp
@@ -1,7 +1,27 @@
-// license:GPL-2.0+
+// license:BSD-3-Clause
// copyright-holders:Couriersud
/*
- * nld_SN74LS629.c
+ * nld_SN74LS629.cpp
+ *
+ * SN74LS629: VOLTAGE-CONTROLLED OSCILLATORS
+ *
+ * +--------------+
+ * 2FC |1 ++ 16| VCC
+ * 1FC |2 15| QSC VCC
+ * 1RNG |3 14| 2RNG
+ * 1CX1 |4 74LS629 13| 2CX1
+ * 1CX2 |5 12| 2CX2
+ * 1ENQ |6 11| 2ENQ
+ * 1Y |7 10| 2Y
+ * OSC GND |8 9| GND
+ * +--------------+
+ *
+ * Naming conventions follow Texas Instruments datasheet
+ *
+ * NOTE: The CX1 and CX2 pins are not connected!
+ * The capacitor value has to be specified as a parameter.
+ * There are more comments on the challenges of emulating this
+ * chip in the *.c file
*
*/
@@ -38,35 +58,22 @@
* Then just use that to toggle a waveform.
*/
+#include "analog/nlid_twoterm.h"
-#include "nld_74ls629.h"
-#include "netlist/analog/nlid_twoterm.h"
+namespace netlist::devices {
-namespace netlist
-{
- namespace devices
- {
- NETLIB_OBJECT(SN74LS629clk)
+ struct SN74LS629clk
{
- NETLIB_CONSTRUCTOR(SN74LS629clk)
- , m_FB(*this, "FB")
- , m_Y(*this, "Y")
- , m_enableq(*this, "m_enableq", 1)
- , m_out(*this, "m_out", 0)
- , m_inc(*this, "m_inc", netlist_time::zero())
- {
- connect(m_FB, m_Y);
- }
-
- NETLIB_RESETI()
+ SN74LS629clk(device_t &owner)
+ : m_FB(owner, "FB", nl_delegate(&SN74LS629clk::fb, this))
+ , m_Y(owner, "Y")
+ , m_enableq(owner, "m_enableq", 0)
+ , m_out(owner, "m_out", 0)
+ , m_inc(owner, "m_inc", netlist_time::zero())
{
- m_enableq = 0;
- m_out = 0;
- m_inc = netlist_time::zero();
+ owner.connect("FB", "Y");
}
- NETLIB_UPDATEI();
-
public:
logic_input_t m_FB;
logic_output_t m_Y;
@@ -74,168 +81,127 @@ namespace netlist
state_var<netlist_sig_t> m_enableq;
state_var<netlist_sig_t> m_out;
state_var<netlist_time> m_inc;
+
+ private:
+ NETLIB_HANDLERI(fb)
+ {
+ if (!m_enableq)
+ {
+ m_out = m_out ^ 1;
+ m_Y.push(m_out, m_inc);
+ }
+ else
+ {
+ m_Y.push(1, m_inc);
+ }
+ }
+
};
NETLIB_OBJECT(SN74LS629)
{
NETLIB_CONSTRUCTOR(SN74LS629)
- , m_clock(*this, "OSC")
+ , m_clock(*this)
, m_R_FC(*this, "R_FC")
, m_R_RNG(*this, "R_RNG")
- , m_ENQ(*this, "ENQ")
- , m_RNG(*this, "RNG")
- , m_FC(*this, "FC")
- , m_CAP(*this, "CAP", 1e-6)
+ , m_ENQ(*this, "ENQ", NETLIB_DELEGATE(inputs))
+ , m_RNG(*this, "RNG", NETLIB_DELEGATE(inputs))
+ , m_FC(*this, "FC", NETLIB_DELEGATE(inputs))
+ , m_CAP(*this, "CAP", nlconst::magic(1e-6))
+ , m_power_pins(*this)
+ , m_power_pins_osc(*this, "OSCVCC", "OSCGND")
{
- register_subalias("GND", m_R_FC.m_N);
+ connect("OSCGND", "R_FC.2");
- connect(m_FC, m_R_FC.m_P);
- connect(m_RNG, m_R_RNG.m_P);
- connect(m_R_FC.m_N, m_R_RNG.m_N);
-
- register_subalias("Y", m_clock.m_Y);
+ connect("FC", "R_FC.1");
+ connect("RNG", "R_RNG.1");
+ connect("R_FC.2", "R_RNG.2");
}
+ private:
NETLIB_RESETI()
{
- m_R_FC.set_R(90000.0);
- m_R_RNG.set_R(90000.0);
- m_clock.reset();
+ m_R_FC().set_R( nlconst::magic(90000.0));
+ m_R_RNG().set_R(nlconst::magic(90000.0));
}
- NETLIB_UPDATEI();
NETLIB_UPDATE_PARAMI()
{
/* update param may be called from anywhere, update_dev(time) is not a good idea */
}
- public:
- NETLIB_SUB(SN74LS629clk) m_clock;
- analog::NETLIB_SUB(R_base) m_R_FC;
- analog::NETLIB_SUB(R_base) m_R_RNG;
+ SN74LS629clk m_clock;
+ NETLIB_SUB_NS(analog, R_base) m_R_FC;
+ NETLIB_SUB_NS(analog, R_base) m_R_RNG;
logic_input_t m_ENQ;
analog_input_t m_RNG;
analog_input_t m_FC;
- param_double_t m_CAP;
- };
-
- NETLIB_OBJECT(SN74LS629_dip)
- {
- NETLIB_CONSTRUCTOR(SN74LS629_dip)
- , m_A(*this, "A")
- , m_B(*this, "B")
- {
- register_subalias("1", m_B.m_FC);
- register_subalias("2", m_A.m_FC);
- register_subalias("3", m_A.m_RNG);
-
- register_subalias("6", m_A.m_ENQ);
- register_subalias("7", m_A.m_clock.m_Y);
+ param_fp_t m_CAP;
+ nld_power_pins m_power_pins;
+ nld_power_pins m_power_pins_osc;
- register_subalias("8", m_A.m_R_FC.m_N);
- register_subalias("9", m_A.m_R_FC.m_N);
- connect(m_A.m_R_FC.m_N, m_B.m_R_FC.m_N);
-
- register_subalias("10", m_B.m_clock.m_Y);
-
- register_subalias("11", m_B.m_ENQ);
- register_subalias("14", m_B.m_RNG);
- }
-
- NETLIB_UPDATEI() { }
-
- NETLIB_RESETI()
+ NETLIB_HANDLERI(inputs)
{
- m_A.reset();
- m_B.reset();
+ {
+ // recompute
+ nl_fptype v_freq = m_FC();
+ nl_fptype v_rng = m_RNG();
+
+ /* coefficients */
+ const nl_fptype k1 = nlconst::magic( 1.9904769024796283E+03);
+ const nl_fptype k2 = nlconst::magic( 1.2070059213983407E+03);
+ const nl_fptype k3 = nlconst::magic( 1.3266985579561108E+03);
+ const nl_fptype k4 = nlconst::magic(-1.5500979825922698E+02);
+ const nl_fptype k5 = nlconst::magic( 2.8184536266938172E+00);
+ const nl_fptype k6 = nlconst::magic(-2.3503421582744556E+02);
+ const nl_fptype k7 = nlconst::magic(-3.3836786704527788E+02);
+ const nl_fptype k8 = nlconst::magic(-1.3569136703258670E+02);
+ const nl_fptype k9 = nlconst::magic( 2.9914575453819188E+00);
+ const nl_fptype k10 = nlconst::magic( 1.6855569086173170E+00);
+
+ /* scale due to input resistance */
+
+ /* Polyfunctional3D_model created by zunzun.com using sum of squared absolute error */
+
+ nl_fptype v_freq_2 = v_freq * v_freq;
+ nl_fptype v_freq_3 = v_freq_2 * v_freq;
+ nl_fptype v_freq_4 = v_freq_3 * v_freq;
+ nl_fptype freq = k1;
+ freq += k2 * v_freq;
+ freq += k3 * v_freq_2;
+ freq += k4 * v_freq_3;
+ freq += k5 * v_freq_4;
+ freq += k6 * v_rng;
+ freq += k7 * v_rng * v_freq;
+ freq += k8 * v_rng * v_freq_2;
+ freq += k9 * v_rng * v_freq_3;
+ freq += k10 * v_rng * v_freq_4;
+
+ freq *= nlconst::magic(0.1e-6) / m_CAP();
+
+ // FIXME: we need a possibility to remove entries from queue ...
+ // or an exact model ...
+ m_clock.m_inc = netlist_time::from_fp(nlconst::half() / freq);
+ }
+
+ if (!m_clock.m_enableq && m_ENQ())
+ {
+ m_clock.m_enableq = 1;
+ m_clock.m_out = m_clock.m_out ^ 1;
+ m_clock.m_Y.push(m_clock.m_out, netlist_time::from_nsec(1));
+ }
+ else if (m_clock.m_enableq && !m_ENQ())
+ {
+ m_clock.m_enableq = 0;
+ m_clock.m_out = m_clock.m_out ^ 1;
+ m_clock.m_Y.push(m_clock.m_out, netlist_time::from_nsec(1));
+ }
}
- private:
- NETLIB_SUB(SN74LS629) m_A;
- NETLIB_SUB(SN74LS629) m_B;
};
+ NETLIB_DEVICE_IMPL(SN74LS629, "SN74LS629", "CAP,@VCC,@GND")
- NETLIB_UPDATE(SN74LS629clk)
- {
- if (!m_enableq)
- {
- m_out = m_out ^ 1;
- m_Y.push(m_out, m_inc);
- }
- else
- {
- m_Y.push(1, m_inc);
- }
- }
-
- NETLIB_UPDATE(SN74LS629)
- {
- {
- // recompute
- nl_double freq;
- nl_double v_freq_2, v_freq_3, v_freq_4;
- nl_double v_freq = m_FC();
- nl_double v_rng = m_RNG();
-
- /* coefficients */
- const nl_double k1 = 1.9904769024796283E+03;
- const nl_double k2 = 1.2070059213983407E+03;
- const nl_double k3 = 1.3266985579561108E+03;
- const nl_double k4 = -1.5500979825922698E+02;
- const nl_double k5 = 2.8184536266938172E+00;
- const nl_double k6 = -2.3503421582744556E+02;
- const nl_double k7 = -3.3836786704527788E+02;
- const nl_double k8 = -1.3569136703258670E+02;
- const nl_double k9 = 2.9914575453819188E+00;
- const nl_double k10 = 1.6855569086173170E+00;
-
- /* scale due to input resistance */
-
- /* Polyfunctional3D_model created by zunzun.com using sum of squared absolute error */
-
- v_freq_2 = v_freq * v_freq;
- v_freq_3 = v_freq_2 * v_freq;
- v_freq_4 = v_freq_3 * v_freq;
- freq = k1;
- freq += k2 * v_freq;
- freq += k3 * v_freq_2;
- freq += k4 * v_freq_3;
- freq += k5 * v_freq_4;
- freq += k6 * v_rng;
- freq += k7 * v_rng * v_freq;
- freq += k8 * v_rng * v_freq_2;
- freq += k9 * v_rng * v_freq_3;
- freq += k10 * v_rng * v_freq_4;
-
- freq *= plib::constants<nl_double>::cast(0.1e-6) / m_CAP();
-
- // FIXME: we need a possibility to remove entries from queue ...
- // or an exact model ...
- m_clock.m_inc = netlist_time::from_double(0.5 / freq);
- //m_clock.update();
-
- //NL_VERBOSE_OUT(("{1} {2} {3} {4}\n", name(), v_freq, v_rng, freq));
- }
-
- if (!m_clock.m_enableq && m_ENQ())
- {
- m_clock.m_enableq = 1;
- m_clock.m_out = m_clock.m_out ^ 1;
- m_clock.m_Y.push(m_clock.m_out, netlist_time::from_nsec(1));
- }
- else if (m_clock.m_enableq && !m_ENQ())
- {
- m_clock.m_enableq = 0;
- m_clock.m_out = m_clock.m_out ^ 1;
- m_clock.m_Y.push(m_clock.m_out, netlist_time::from_nsec(1));
- }
- }
-
- NETLIB_DEVICE_IMPL(SN74LS629, "SN74LS629", "CAP")
- NETLIB_DEVICE_IMPL(SN74LS629_dip, "SN74LS629_DIP", "1.CAP1,2.CAP2")
-
- } //namespace devices
-} // namespace netlist
+} // namespace netlist::devices