My Project  0.0.16
QUCS Mapping
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
digital.cpp
Go to the documentation of this file.
1 /*
2  * digital.cpp - digital base class implementation
3  *
4  * Copyright (C) 2005, 2006, 2009 Stefan Jahn <stefan@lkcc.org>
5  *
6  * This is free software; you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License as published by
8  * the Free Software Foundation; either version 2, or (at your option)
9  * any later version.
10  *
11  * This software is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14  * GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with this package; see the file COPYING. If not, write to
18  * the Free Software Foundation, Inc., 51 Franklin Street - Fifth Floor,
19  * Boston, MA 02110-1301, USA.
20  *
21  * $Id: digital.cpp 1825 2011-03-11 20:42:14Z ela $
22  *
23  */
24 
25 #if HAVE_CONFIG_H
26 # include <config.h>
27 #endif
28 
29 #include <stdio.h>
30 #include <stdlib.h>
31 #include <math.h>
32 
33 #include "complex.h"
34 #include "object.h"
35 #include "circuit.h"
36 #include "constants.h"
37 #include "digital.h"
38 
39 #define NODE_OUT 0 /* first node is output node */
40 #define NODE_IN1 1 /* input nodes start here */
41 
42 // Constructor.
45  g = NULL;
46  Vout = 0;
47  Tdelay = 0;
48  delay = false;
49 }
50 
51 // Destructor.
53  freeDigital ();
54 }
55 
56 // Reserve space for derivatives.
57 void digital::initDigital (void) {
58  if (g == NULL) {
59  g = (nr_double_t *) malloc ((getSize () - 1) * sizeof (nr_double_t));
60  }
61 }
62 
63 // Free space of derivatives if necessary.
64 void digital::freeDigital (void) {
65  if (g != NULL) {
66  free (g);
67  g = NULL;
68  }
69 }
70 
71 // Returns voltage at given input node.
72 nr_double_t digital::getVin (int input) {
73  if (delay) {
74  return real (getV (NODE_IN1 + input, Tdelay));
75  } else {
76  return real (getV (NODE_IN1 + input));
77  }
78 }
79 
80 // Computes the transfer function for the given input node.
81 nr_double_t digital::calcTransferX (int input) {
82  nr_double_t v = getPropertyDouble ("V");
83  nr_double_t t = getPropertyDouble ("TR");
84  return tanh (t * (getVin (input) / v - 0.5));
85 }
86 
87 // Computes a slightly modified transfer function.
88 nr_double_t digital::calcTransfer (int input) {
89  return (1 - GMin) * calcTransferX (input);
90 }
91 
92 // Computes the transfer functions derivative for the given input node.
93 nr_double_t digital::calcDerivativeX (int input) {
94  nr_double_t v = getPropertyDouble ("V");
95  nr_double_t t = getPropertyDouble ("TR");
96  nr_double_t x = tanh (t * (getVin (input) / v - 0.5));
97  return t * (1 - x * x);
98 }
99 
100 // Computes a slightly modified transfer functions derivative.
101 nr_double_t digital::calcDerivative (int input) {
102  return (1 - GMin) * calcDerivativeX (input);
103 }
104 
105 // Setup constant S-parameter entries.
106 void digital::initSP (void) {
107  allocMatrixS ();
108  setS (NODE_OUT, NODE_OUT, -1);
109  for (i = 0; i < getSize () - 1; i++) {
110  setS (NODE_IN1 + i, NODE_IN1 + i, +1);
111  }
112 }
113 
114 // Setup frequency dependent S-parameter entries.
115 void digital::calcSP (nr_double_t frequency) {
116  nr_double_t t = getPropertyDouble ("t");
117  for (i = 0; i < getSize () - 1; i++) {
118  setS (NODE_OUT, NODE_IN1 + i,
119  4.0 * polar (g[i], - 2.0 * M_PI * frequency * t));
120  }
121 }
122 
123 // Initialize constant MNA entries for DC analysis.
124 void digital::initDC (void) {
125  initDigital ();
126  allocMatrixMNA ();
127  delay = false;
128  setB (NODE_OUT, VSRC_1, +1);
129  setC (VSRC_1, NODE_OUT, -1);
130  setE (VSRC_1, 0);
131 }
132 
133 // Computes variable MNA entries during DC analysis.
134 void digital::calcDC (void) {
135  calcOutput ();
136  calcDerivatives ();
137  for (i = 0, Veq = 0; i < getSize () - 1; i++) {
138  setC (VSRC_1, NODE_IN1 + i, g[i]);
139  Veq += g[i] * getVin (i);
140  }
141  setE (VSRC_1, Veq - Vout);
142 }
143 
145  calcDerivatives ();
146 }
147 
148 // Initialize constant MNA entries for AC analysis.
149 void digital::initAC (void) {
150  initDC ();
151 }
152 
153 // Computes frequency dependent MNA entries during AC analysis.
154 void digital::calcAC (nr_double_t frequency) {
155  nr_double_t t = getPropertyDouble ("t");
156  for (i = 0; i < getSize () - 1; i++) {
157  setC (VSRC_1, NODE_IN1 + i, polar (g[i], - 2.0 * M_PI * frequency * t));
158  }
159 }
160 
161 // Initialize transient analysis.
162 void digital::initTR (void) {
163  nr_double_t t = getPropertyDouble ("t");
164  initDC ();
165  deleteHistory ();
166  if (t > 0.0) {
167  delay = true;
168  setHistory (true);
169  initHistory (t);
170  setC (VSRC_1, NODE_OUT, 1);
171  }
172 }
173 
174 // Computes MNA entries during transient analysis.
175 void digital::calcTR (nr_double_t t) {
176  if (delay) {
177  Tdelay = t - getPropertyDouble ("t");
178  calcOutput ();
179  setE (VSRC_1, Vout);
180  }
181  else {
182  calcDC ();
183  }
184 }