summaryrefslogtreecommitdiffstatshomepage
path: root/src/lib/netlist/analog/nld_opamps.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/lib/netlist/analog/nld_opamps.cpp')
-rw-r--r--src/lib/netlist/analog/nld_opamps.cpp180
1 files changed, 180 insertions, 0 deletions
diff --git a/src/lib/netlist/analog/nld_opamps.cpp b/src/lib/netlist/analog/nld_opamps.cpp
new file mode 100644
index 00000000000..38a32b0d211
--- /dev/null
+++ b/src/lib/netlist/analog/nld_opamps.cpp
@@ -0,0 +1,180 @@
+// license:GPL-2.0+
+// copyright-holders:Couriersud
+/*
+ * nld_opamps.c
+ *
+ */
+
+#include "nld_opamps.h"
+#include "devices/net_lib.h"
+
+NETLIST_START(opamp_lm3900)
+
+ /*
+ * Fast norton opamp model without bandwidth
+ */
+
+ /* Terminal definitions for calling netlists */
+
+ ALIAS(PLUS, R1.1) // Positive input
+ ALIAS(MINUS, R2.1) // Negative input
+ ALIAS(OUT, G1.OP) // Opamp output ...
+ ALIAS(VM, G1.ON) // V- terminal
+ ALIAS(VP, DUMMY.I) // V+ terminal
+
+ DUMMY_INPUT(DUMMY)
+
+ /* The opamp model */
+
+ RES(R1, 1)
+ RES(R2, 1)
+ NET_C(R1.1, G1.IP)
+ NET_C(R2.1, G1.IN)
+ NET_C(R1.2, R2.2, G1.ON)
+ VCVS(G1)
+ PARAM(G1.G, 10000000)
+ //PARAM(G1.RI, 1)
+ PARAM(G1.RO, RES_K(8))
+
+NETLIST_END()
+
+NETLIB_NAMESPACE_DEVICES_START()
+
+/*
+ * Type = 0: Impedance changer
+ * 1; Idealized opamp
+ * 2; opamp with first pole
+ * 3: opamp with first pole + output limit
+ * 4: opamp with input stage, first pole + output limit
+ */
+
+NETLIB_START(OPAMP)
+{
+ register_param("MODEL", m_model, "");
+
+ m_type = m_model.model_value("TYPE");
+
+ register_input("VCC", m_VCC);
+ register_input("GND", m_GND);
+
+ register_output("VL", m_VL);
+ register_output("VH", m_VH);
+ register_output("VREF", m_VREF);
+
+ register_sub("G1", m_G1);
+ register_sub("RP1", m_RP);
+
+ if (m_type == 1)
+ {
+ register_subalias("PLUS", "G1.IP");
+ register_subalias("MINUS", "G1.IN");
+ register_subalias("OUT", "G1.OP");
+
+ connect_late("G1.ON", "VREF");
+ connect_late("RP1.2", "VREF");
+ connect_late("RP1.1", "G1.OP");
+
+ }
+ else if (m_type == 3)
+ {
+ register_sub("CP1", m_CP);
+ register_sub("EBUF", m_EBUF);
+ register_sub("DN", m_DN);
+ register_sub("DP", m_DP);
+
+ register_subalias("PLUS", "G1.IP");
+ register_subalias("MINUS", "G1.IN");
+ register_subalias("OUT", "EBUF.OP");
+
+ connect_late("EBUF.ON", "VREF");
+
+ connect_late("G1.ON", "VREF");
+ connect_late("RP1.2", "VREF");
+ connect_late("CP1.2", "VREF");
+ connect_late("EBUF.IN", "VREF");
+
+ connect_late("RP1.1", "G1.OP");
+ connect_late("CP1.1", "RP1.1");
+
+ connect_late("DP.K", "VH");
+ connect_late("VL", "DN.A");
+ connect_late("DP.A", "DN.K");
+ connect_late("DN.K", "RP1.1");
+ connect_late("EBUF.IP", "RP1.1");
+ }
+ else
+ netlist().log().fatal("Unknown opamp type: {1}", m_type);
+}
+
+/* .model abc OPAMP(VLH=2.0 VLL=0.2 FPF=5 UGF=10k SLEW=0.6u RI=1000k RO=50 DAB=0.002)
+ *
+ * Differential Amp Bias ~ op amp's total quiescent current.
+ * */
+
+NETLIB_UPDATE(OPAMP)
+{
+ const double cVt = 0.0258 * 1.0; // * m_n;
+ const double cId = m_model.model_value("DAB"); // 3 mA
+ const double cVd = cVt * nl_math::log(cId / 1e-15 + 1.0);
+ m_VH.set_Q(INPANALOG(m_VCC) - m_model.model_value("VLH") - cVd);
+ m_VL.set_Q(INPANALOG(m_GND) + m_model.model_value("VLL") + cVd);
+ m_VREF.set_Q((INPANALOG(m_VCC) + INPANALOG(m_GND)) / 2.0);
+}
+
+NETLIB_RESET(OPAMP)
+{
+ m_G1.do_reset();
+ m_G1.m_RI.setTo(m_model.model_value("RI"));
+
+ if (m_type == 1)
+ {
+ double RO = m_model.model_value("RO");
+ double G = m_model.model_value("UGF") / m_model.model_value("FPF") / RO;
+ m_RP.set_R(RO);
+ m_G1.m_G.setTo(G);
+ }
+ else if (m_type == 3)
+ {
+ m_EBUF.do_reset();
+ m_DP.do_reset();
+ m_DN.do_reset();
+ m_CP.do_reset();
+ m_RP.do_reset();
+
+ m_EBUF.m_G.setTo(1.0);
+ m_EBUF.m_RO.setTo(m_model.model_value("RO"));
+ m_DP.m_model.setTo("D(IS=1e-15 N=1)");
+ m_DN.m_model.setTo("D(IS=1e-15 N=1)");
+
+ double CP = m_model.model_value("DAB") / m_model.model_value("SLEW");
+ double RP = 0.5 / 3.1459 / CP / m_model.model_value("FPF");
+ double G = m_model.model_value("UGF") / m_model.model_value("FPF") / RP;
+
+ m_CP.m_C.setTo(CP);
+ m_RP.set_R(RP);
+ m_G1.m_G.setTo(G);
+
+ }
+
+
+}
+
+NETLIB_UPDATE_PARAM(OPAMP)
+{
+}
+
+/*
+NETLIB_DEVICE_WITH_PARAMS(OPAMPx,
+ NETLIB_NAME(R) m_RP;
+ NETLIB_NAME(C) m_CP;
+ NETLIB_NAME(VCCS) m_G1;
+ NETLIB_NAME(VCVS) m_EBUF;
+
+ param_model_t m_model;
+ analog_input_t m_VH;
+ analog_input_t m_VL;
+ analog_input_t m_VREF;
+);
+*/
+
+NETLIB_NAMESPACE_DEVICES_END()