Qucs-core  0.0.19
digital.cpp
Go to the documentation of this file.
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 }