diff options
Diffstat (limited to 'src/lib/netlist/devices/nld_74ls629.cpp')
-rw-r--r-- | src/lib/netlist/devices/nld_74ls629.cpp | 282 |
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 |