Qucs-core
0.0.19
|
00001 /* 00002 * digital.cpp - digital base class implementation 00003 * 00004 * Copyright (C) 2005, 2006, 2009 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 <stdio.h> 00030 #include <stdlib.h> 00031 #include <cmath> 00032 00033 #include "complex.h" 00034 #include "object.h" 00035 #include "circuit.h" 00036 #include "constants.h" 00037 #include "digital.h" 00038 00039 #define NODE_OUT 0 /* first node is output node */ 00040 #define NODE_IN1 1 /* input nodes start here */ 00041 00042 using namespace qucs; 00043 00044 // Constructor. 00045 digital::digital () : circuit () { 00046 setVoltageSources (1); 00047 g = NULL; 00048 Vout = 0; 00049 Tdelay = 0; 00050 delay = false; 00051 } 00052 00053 // Destructor. 00054 digital::~digital () { 00055 freeDigital (); 00056 } 00057 00058 // Reserve space for derivatives. 00059 void digital::initDigital (void) { 00060 if (g == NULL) { 00061 g = (nr_double_t *) malloc ((getSize () - 1) * sizeof (nr_double_t)); 00062 } 00063 } 00064 00065 // Free space of derivatives if necessary. 00066 void digital::freeDigital (void) { 00067 if (g != NULL) { 00068 free (g); 00069 g = NULL; 00070 } 00071 } 00072 00073 // Returns voltage at given input node. 00074 nr_double_t digital::getVin (int input) { 00075 if (delay) { 00076 return real (getV (NODE_IN1 + input, Tdelay)); 00077 } else { 00078 return real (getV (NODE_IN1 + input)); 00079 } 00080 } 00081 00082 // Computes the transfer function for the given input node. 00083 nr_double_t digital::calcTransferX (int input) { 00084 nr_double_t v = getPropertyDouble ("V"); 00085 nr_double_t t = getPropertyDouble ("TR"); 00086 return std::tanh (t * (getVin (input) / v - 0.5)); 00087 } 00088 00089 // Computes a slightly modified transfer function. 00090 nr_double_t digital::calcTransfer (int input) { 00091 return (1 - GMin) * calcTransferX (input); 00092 } 00093 00094 // Computes the transfer functions derivative for the given input node. 00095 nr_double_t digital::calcDerivativeX (int input) { 00096 nr_double_t v = getPropertyDouble ("V"); 00097 nr_double_t t = getPropertyDouble ("TR"); 00098 nr_double_t x = std::tanh (t * (getVin (input) / v - 0.5)); 00099 return t * (1 - x * x); 00100 } 00101 00102 // Computes a slightly modified transfer functions derivative. 00103 nr_double_t digital::calcDerivative (int input) { 00104 return (1 - GMin) * calcDerivativeX (input); 00105 } 00106 00107 // Setup constant S-parameter entries. 00108 void digital::initSP (void) { 00109 allocMatrixS (); 00110 setS (NODE_OUT, NODE_OUT, -1); 00111 for (i = 0; i < getSize () - 1; i++) { 00112 setS (NODE_IN1 + i, NODE_IN1 + i, +1); 00113 } 00114 } 00115 00116 // Setup frequency dependent S-parameter entries. 00117 void digital::calcSP (nr_double_t frequency) { 00118 nr_double_t t = getPropertyDouble ("t"); 00119 for (i = 0; i < getSize () - 1; i++) { 00120 setS (NODE_OUT, NODE_IN1 + i, 00121 4.0 * std::polar (g[i], - 2.0 * pi * frequency * t)); 00122 } 00123 } 00124 00125 // Initialize constant MNA entries for DC analysis. 00126 void digital::initDC (void) { 00127 initDigital (); 00128 allocMatrixMNA (); 00129 delay = false; 00130 setB (NODE_OUT, VSRC_1, +1); 00131 setC (VSRC_1, NODE_OUT, -1); 00132 setE (VSRC_1, 0); 00133 } 00134 00135 // Computes variable MNA entries during DC analysis. 00136 void digital::calcDC (void) { 00137 calcOutput (); 00138 calcDerivatives (); 00139 for (i = 0, Veq = 0; i < getSize () - 1; i++) { 00140 setC (VSRC_1, NODE_IN1 + i, g[i]); 00141 Veq += g[i] * getVin (i); 00142 } 00143 setE (VSRC_1, Veq - Vout); 00144 } 00145 00146 void digital::calcOperatingPoints (void) { 00147 calcDerivatives (); 00148 } 00149 00150 // Initialize constant MNA entries for AC analysis. 00151 void digital::initAC (void) { 00152 initDC (); 00153 } 00154 00155 // Computes frequency dependent MNA entries during AC analysis. 00156 void digital::calcAC (nr_double_t frequency) { 00157 nr_double_t t = getPropertyDouble ("t"); 00158 for (i = 0; i < getSize () - 1; i++) { 00159 setC (VSRC_1, NODE_IN1 + i, std::polar (g[i], - 2.0 * pi * frequency * t)); 00160 } 00161 } 00162 00163 // Initialize transient analysis. 00164 void digital::initTR (void) { 00165 nr_double_t t = getPropertyDouble ("t"); 00166 initDC (); 00167 deleteHistory (); 00168 if (t > 0.0) { 00169 delay = true; 00170 setHistory (true); 00171 initHistory (t); 00172 setC (VSRC_1, NODE_OUT, 1); 00173 } 00174 } 00175 00176 // Computes MNA entries during transient analysis. 00177 void digital::calcTR (nr_double_t t) { 00178 if (delay) { 00179 Tdelay = t - getPropertyDouble ("t"); 00180 calcOutput (); 00181 setE (VSRC_1, Vout); 00182 } 00183 else { 00184 calcDC (); 00185 } 00186 }