Qucs-core
0.0.19
|
00001 /* 00002 * opamp.cpp - operational amplifier class implementation 00003 * 00004 * Copyright (C) 2004, 2008 Stefan Jahn <stefan@lkcc.org> 00005 * 00006 * This is free software; you can redistribute it and/or modify 00007 * it under the terms of the GNU General Public License as published by 00008 * the Free Software Foundation; either version 2, or (at your option) 00009 * any later version. 00010 * 00011 * This software is distributed in the hope that it will be useful, 00012 * but WITHOUT ANY WARRANTY; without even the implied warranty of 00013 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00014 * GNU General Public License for more details. 00015 * 00016 * You should have received a copy of the GNU General Public License 00017 * along with this package; see the file COPYING. If not, write to 00018 * the Free Software Foundation, Inc., 51 Franklin Street - Fifth Floor, 00019 * Boston, MA 02110-1301, USA. 00020 * 00021 * $Id$ 00022 * 00023 */ 00024 00025 #if HAVE_CONFIG_H 00026 # include <config.h> 00027 #endif 00028 00029 #include "component.h" 00030 #include "opamp.h" 00031 00032 #define NODE_INM 0 00033 #define NODE_INP 1 00034 #define NODE_OUT 2 00035 00036 using namespace qucs; 00037 00038 opamp::opamp () : circuit (3) { 00039 type = CIR_OPAMP; 00040 setVoltageSources (1); 00041 } 00042 00043 void opamp::initSP (void) { 00044 allocMatrixS (); 00045 setS (NODE_INP, NODE_INP, 1); 00046 setS (NODE_INP, NODE_OUT, 0); 00047 setS (NODE_INP, NODE_INM, 0); 00048 setS (NODE_INM, NODE_INP, 0); 00049 setS (NODE_INM, NODE_OUT, 0); 00050 setS (NODE_INM, NODE_INM, 1); 00051 setS (NODE_OUT, NODE_INP, +4 * gv); 00052 setS (NODE_OUT, NODE_OUT, -1); 00053 setS (NODE_OUT, NODE_INM, -4 * gv); 00054 } 00055 00056 void opamp::initDC (void) { 00057 allocMatrixMNA (); 00058 setB (NODE_INP, VSRC_1, 0); 00059 setB (NODE_OUT, VSRC_1, 1); 00060 setB (NODE_INM, VSRC_1, 0); 00061 setC (VSRC_1, NODE_OUT, -1); setD (VSRC_1, VSRC_1, 0); setE (VSRC_1, 0); 00062 } 00063 00064 void opamp::calcDC (void) { 00065 nr_double_t g = getPropertyDouble ("G"); 00066 nr_double_t uMax = getPropertyDouble ("Umax"); 00067 nr_double_t Uin = real (getV (NODE_INP) - getV (NODE_INM)); 00068 nr_double_t Uout = uMax * two_over_pi * qucs::atan (Uin * g * pi_over_2 / uMax); 00069 gv = g / (1 + sqr (pi_over_2 / uMax * g * Uin)) + GMin; 00070 setC (VSRC_1, NODE_INP, +gv); 00071 setC (VSRC_1, NODE_INM, -gv); 00072 setE (VSRC_1, Uin * gv - Uout); 00073 } 00074 00075 void opamp::calcOperatingPoints (void) { 00076 setOperatingPoint ("g", gv); 00077 } 00078 00079 void opamp::initAC (void) { 00080 initDC (); 00081 setC (VSRC_1, NODE_INP, +gv); 00082 setC (VSRC_1, NODE_INM, -gv); 00083 } 00084 00085 void opamp::initTR (void) { 00086 initDC (); 00087 } 00088 00089 void opamp::calcTR (nr_double_t) { 00090 calcDC (); 00091 } 00092 00093 // properties 00094 PROP_REQ [] = { 00095 { "G", PROP_REAL, { 1e6, PROP_NO_STR }, PROP_MIN_VAL (1) }, 00096 PROP_NO_PROP }; 00097 PROP_OPT [] = { 00098 { "Umax", PROP_REAL, { 15, PROP_NO_STR }, PROP_POS_RANGE }, 00099 PROP_NO_PROP }; 00100 struct define_t opamp::cirdef = 00101 { "OpAmp", 3, PROP_COMPONENT, PROP_NO_SUBSTRATE, PROP_NONLINEAR, PROP_DEF };