diff --git a/src/lib/netlist/devices/net_lib.cpp b/src/lib/netlist/devices/net_lib.cpp index a105406149c..5250135feb8 100644 --- a/src/lib/netlist/devices/net_lib.cpp +++ b/src/lib/netlist/devices/net_lib.cpp @@ -50,10 +50,10 @@ NETLIST_START(bjt_models) NETLIST_END() NETLIST_START(family_models) - NET_MODEL("FAMILY _(TYPE=CUSTOM IVL=0.8 IVH=2.0 OVL=0.1 OVH=4.0 ORL=1.0 ORH=130.0)") + NET_MODEL("FAMILY _(TYPE=CUSTOM FV=5 IVL=0.16 IVH=0.4 OVL=0.1 OVH=1.0 ORL=1.0 ORH=130.0)") NET_MODEL("OPAMP _()") - NET_MODEL("74XXOC FAMILY(IVL=0.8 IVH=2.0 OVL=0.1 OVH=4.95 ORL=10.0 ORH=1.0e8)") + NET_MODEL("74XXOC FAMILY(FV=5 IVL=0.16 IVH=0.4 OVL=0.1 OVH=0.05 ORL=10.0 ORH=1.0e8)") NET_MODEL("74XX FAMILY(TYPE=TTL)") NET_MODEL("CD4XXX FAMILY(TYPE=CD4XXX)") NETLIST_END() diff --git a/src/lib/netlist/devices/nlid_proxy.cpp b/src/lib/netlist/devices/nlid_proxy.cpp index d32ba00afe1..6ecad8656a2 100644 --- a/src/lib/netlist/devices/nlid_proxy.cpp +++ b/src/lib/netlist/devices/nlid_proxy.cpp @@ -28,6 +28,7 @@ namespace netlist , m_last_state(*this, "m_last_var", -1) , m_is_timestep(false) { + const char *power_syms[3][2] ={ {"VCC", "VEE"}, {"VCC", "GND"}, {"VDD", "VSS"}}; //register_sub(m_RV); //register_term("1", m_RV.m_P); //register_term("2", m_RV.m_N); @@ -35,19 +36,42 @@ namespace netlist register_subalias("Q", m_RV.m_P); connect_late(m_RV.m_N, m_GNDHack); + bool f = false; + for (int i = 0; i < 3; i++) + { + pstring devname = out_proxied->device().name(); + auto tp = netlist().setup().find_terminal(devname + "." + power_syms[i][0], detail::device_object_t::type_t::INPUT, false); + auto tn = netlist().setup().find_terminal(devname + "." + power_syms[i][1], detail::device_object_t::type_t::INPUT, false); + if (tp != nullptr && tn != nullptr) + { + /* alternative logic */ + f = true; + } + } + if (!f) + netlist().log().warning("D/A Proxy: Found no valid combination of power terminals on device {1}", out_proxied->device().name()); + else + netlist().log().warning("D/A Proxy: Found power terminals on device {1}", out_proxied->device().name()); +#if (0) printf("%s %s\n", out_proxied->name().cstr(), out_proxied->device().name().cstr()); auto x = netlist().setup().find_terminal(out_proxied->name(), detail::device_object_t::type_t::OUTPUT, false); if (x) printf("==> %s\n", x->name().cstr()); +#endif } void nld_d_to_a_proxy::reset() { + // FIXME: Variable voltage + double supply_V = logic_family().fixed_V(); + if (supply_V == 0.0) supply_V = 5.0; + //m_Q.initial(0.0); m_last_state = -1; m_RV.do_reset(); m_is_timestep = m_RV.m_P.net().solver()->has_timestep_devices(); - m_RV.set(NL_FCONST(1.0) / logic_family().m_R_low, logic_family().m_low_V, 0.0); + m_RV.set(NL_FCONST(1.0) / logic_family().R_low(), + logic_family().low_V(0.0, supply_V), 0.0); } NETLIB_UPDATE(d_to_a_proxy) @@ -55,9 +79,12 @@ namespace netlist const int state = static_cast(m_I()); if (state != m_last_state) { + // FIXME: Variable voltage + double supply_V = logic_family().fixed_V(); + if (supply_V == 0.0) supply_V = 5.0; m_last_state = state; - const nl_double R = state ? logic_family().m_R_high : logic_family().m_R_low; - const nl_double V = state ? logic_family().m_high_V : logic_family().m_low_V; + const nl_double R = state ? logic_family().R_high() : logic_family().R_low(); + const nl_double V = state ? logic_family().high_V(0.0, supply_V) : logic_family().low_V(0.0, supply_V); // We only need to update the net first if this is a time stepping net if (m_is_timestep) diff --git a/src/lib/netlist/devices/nlid_proxy.h b/src/lib/netlist/devices/nlid_proxy.h index 0138d0f759d..bcda8fa4e2a 100644 --- a/src/lib/netlist/devices/nlid_proxy.h +++ b/src/lib/netlist/devices/nlid_proxy.h @@ -83,9 +83,13 @@ namespace netlist NETLIB_UPDATEI() { nl_assert(m_logic_family != nullptr); - if (m_I.Q_Analog() > logic_family().m_high_thresh_V) + // FIXME: Variable supply voltage! + double supply_V = logic_family().fixed_V(); + if (supply_V == 0.0) supply_V = 5.0; + + if (m_I.Q_Analog() > logic_family().high_thresh_V(0.0, supply_V)) m_Q.push(1, NLTIME_FROM_NS(1)); - else if (m_I.Q_Analog() < logic_family().m_low_thresh_V) + else if (m_I.Q_Analog() < logic_family().low_thresh_V(0.0, supply_V)) m_Q.push(0, NLTIME_FROM_NS(1)); else { diff --git a/src/lib/netlist/macro/nlm_other.cpp b/src/lib/netlist/macro/nlm_other.cpp index 68c0ea57d36..84a3af4dc04 100644 --- a/src/lib/netlist/macro/nlm_other.cpp +++ b/src/lib/netlist/macro/nlm_other.cpp @@ -36,7 +36,7 @@ static NETLIST_START(MC14584B_DIP) s1.A, /* A1 |1 ++ 14| VCC */ VCC.I, s1.Q, /* Y1 |2 13| A6 */ s6.A, s2.A, /* A2 |3 12| Y6 */ s6.Q, - s2.Q, /* Y2 |4 7416 11| A5 */ s5.A, + s2.Q, /* Y2 |4 MC14584B 11| A5 */ s5.A, s3.A, /* A3 |5 10| Y5 */ s5.Q, s3.Q, /* Y3 |6 9| A4 */ s4.A, GND.I, /* GND |7 8| Y4 */ s4.Q @@ -49,7 +49,8 @@ NETLIST_START(otheric_lib) TT_HEAD(" A | Q ") TT_LINE(" 0 | 1 |100") TT_LINE(" 1 | 0 |100") - TT_FAMILY("FAMILY(IVL=2.1 IVH=2.7 OVL=0.05 OVH=4.95 ORL=10.0 ORH=10.0)") + // 2.1V negative going and 2.7V positive going at 5V + TT_FAMILY("FAMILY(FV=0 IVL=0.42 IVH=0.54 OVL=0.05 OVH=0.05 ORL=10.0 ORH=10.0)") TRUTHTABLE_END() LOCAL_LIB_ENTRY(MC14584B_DIP) diff --git a/src/lib/netlist/nl_base.cpp b/src/lib/netlist/nl_base.cpp index c129c21b72b..76ce59db5ac 100644 --- a/src/lib/netlist/nl_base.cpp +++ b/src/lib/netlist/nl_base.cpp @@ -58,11 +58,12 @@ class logic_family_ttl_t : public logic_family_desc_t public: logic_family_ttl_t() : logic_family_desc_t() { - m_low_thresh_V = 0.8; - m_high_thresh_V = 2.0; + m_fixed_V = 5.0; + m_low_thresh_PCNT = 0.8 / 5.0; + m_high_thresh_PCNT = 2.0 / 5.0; // m_low_V - these depend on sinked/sourced current. Values should be suitable for typical applications. - m_low_V = 0.1; - m_high_V = 4.0; + m_low_VO = 0.1; + m_high_VO = 1.0; // 4.0 m_R_low = 1.0; m_R_high = 130.0; } @@ -77,11 +78,12 @@ class logic_family_cd4xxx_t : public logic_family_desc_t public: logic_family_cd4xxx_t() : logic_family_desc_t() { - m_low_thresh_V = 0.8; - m_high_thresh_V = 2.0; + m_fixed_V = 0.0; + m_low_thresh_PCNT = 1.5 / 5.0; + m_high_thresh_PCNT = 3.5 / 5.0; // m_low_V - these depend on sinked/sourced current. Values should be suitable for typical applications. - m_low_V = 0.05; - m_high_V = 4.95; + m_low_VO = 0.05; + m_high_VO = 0.05; // 4.95 m_R_low = 10.0; m_R_high = 10.0; } diff --git a/src/lib/netlist/nl_base.h b/src/lib/netlist/nl_base.h index 01b3875d7a6..f72665c62bc 100644 --- a/src/lib/netlist/nl_base.h +++ b/src/lib/netlist/nl_base.h @@ -228,12 +228,21 @@ namespace netlist virtual plib::owned_ptr create_d_a_proxy(netlist_t &anetlist, const pstring &name, logic_output_t *proxied) const = 0; - nl_double m_low_thresh_V; //!< low input threshhold. If the input voltage is below this value, a "0" input is signalled - nl_double m_high_thresh_V; //!< high input threshhold. If the input voltage is above this value, a "0" input is signalled - nl_double m_low_V; //!< low output voltage. This voltage is output if the ouput is "0" - nl_double m_high_V; //!< high output voltage. This voltage is output if the ouput is "1" - nl_double m_R_low; //!< low output resistance. Value of series resistor used for low output - nl_double m_R_high; //!< high output resistance. Value of series resistor used for high output + double fixed_V() const { return m_fixed_V; } + double low_thresh_V(const double VN, const double VP) const { return VN + (VP - VN) * m_low_thresh_PCNT; } + double high_thresh_V(const double VN, const double VP) const { return VN + (VP - VN) * m_high_thresh_PCNT; } + double low_V(const double VN, const double VP) const { return VN + m_low_VO; } + double high_V(const double VN, const double VP) const { return VP - m_high_VO; } + double R_low() const { return m_R_low; } + double R_high() const { return m_R_high; } + + double m_fixed_V; //!< For variable voltage families, specify 0. For TTL this would be 5. */ + double m_low_thresh_PCNT; //!< low input threshhold offset. If the input voltage is below this value times supply voltage, a "0" input is signalled + double m_high_thresh_PCNT; //!< high input threshhold offset. If the input voltage is above the value times supply voltage, a "0" input is signalled + double m_low_VO; //!< low output voltage offset. This voltage is output if the ouput is "0" + double m_high_VO; //!< high output voltage offset. The supply voltage minus this offset is output if the ouput is "1" + double m_R_low; //!< low output resistance. Value of series resistor used for low output + double m_R_high; //!< high output resistance. Value of series resistor used for high output }; /*! Base class for devices, terminals, outputs and inputs which support diff --git a/src/lib/netlist/nl_setup.cpp b/src/lib/netlist/nl_setup.cpp index 1023f1a0b28..06cef2a0947 100644 --- a/src/lib/netlist/nl_setup.cpp +++ b/src/lib/netlist/nl_setup.cpp @@ -854,10 +854,11 @@ const logic_family_desc_t *setup_t::family_from_model(const pstring &model) auto ret = plib::make_unique_base(); - ret->m_low_thresh_V = setup_t::model_value(map, "IVL"); - ret->m_high_thresh_V = setup_t::model_value(map, "IVH"); - ret->m_low_V = setup_t::model_value(map, "OVL"); - ret->m_high_V = setup_t::model_value(map, "OVH"); + ret->m_fixed_V = setup_t::model_value(map, "FV"); + ret->m_low_thresh_PCNT = setup_t::model_value(map, "IVL"); + ret->m_high_thresh_PCNT = setup_t::model_value(map, "IVH"); + ret->m_low_VO = setup_t::model_value(map, "OVL"); + ret->m_high_VO = setup_t::model_value(map, "OVH"); ret->m_R_low = setup_t::model_value(map, "ORL"); ret->m_R_high = setup_t::model_value(map, "ORH");