KiCad PCB EDA Suite
Loading...
Searching...
No Matches
coplanar.cpp
Go to the documentation of this file.
1/*
2 * coplanar.cpp - coplanar class implementation
3 *
4 * Copyright (C) 2008 Michael Margraf <[email protected]>
5 * Copyright (C) 2005, 2006 Stefan Jahn <[email protected]>
6 * Modified for Kicad: 2011 jean-pierre.charras
7 *
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation; either version 2 of the License, or (at
11 * your option) any later version.
12 *
13 * This program is distributed in the hope that it will be useful, but
14 * WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 * General Public License for more details.
17 *
18 * You should have received a copy of the GNU General Public License
19 * along with this package; see the file COPYING. If not, write to
20 * the Free Software Foundation, Inc., 51 Franklin Street - Fifth Floor,
21 * Boston, MA 02110-1301, USA.
22 *
23 */
24
25
26#include <cmath>
27#include <cstdio>
28#include <cstdlib>
29#include <cstring>
30
31#include "coplanar.h"
32#include "units.h"
33
35{
36 m_Name = "CoPlanar";
37 backMetal = false;
38 unit_prop_delay = 0.0;
39 Init();
40}
41
42
44{
45 m_Name = "GrCoPlanar";
46 backMetal = true;
47}
48
49
50// -------------------------------------------------------------------
52{
54
55 // other local variables (quasi-static constants)
56 double k1, kk1, kpk1, k2, k3, q1, q2, q3 = 0, qz, er0 = 0;
57 double zl_factor;
58
59 // compute the necessary quasi-static approx. (K1, K3, er(0) and Z(0))
62 kk1 = ellipk( k1 );
63 kpk1 = ellipk( sqrt( 1 - k1 * k1 ) );
64 q1 = kk1 / kpk1;
65
66
67 // backside is metal
68 if( backMetal )
69 {
70 k3 = tanh( ( M_PI / 4 ) * ( m_parameters[PHYS_WIDTH_PRM] / m_parameters[H_PRM] ) )
71 / tanh( ( M_PI / 4 )
75 q3 = ellipk( k3 ) / ellipk( sqrt( 1 - k3 * k3 ) );
76 qz = 1 / ( q1 + q3 );
77 er0 = 1 + q3 * qz * ( m_parameters[EPSILONR_PRM] - 1 );
78 zl_factor = ZF0 / 2 * qz;
79 }
80 // backside is air
81 else
82 {
83 k2 = sinh( ( M_PI / 4 ) * ( m_parameters[PHYS_WIDTH_PRM] / m_parameters[H_PRM] ) )
84 / sinh( ( M_PI / 4 )
88 q2 = ellipk( k2 ) / ellipk( sqrt( 1 - k2 * k2 ) );
89 er0 = 1 + ( m_parameters[EPSILONR_PRM] - 1 ) / 2 * q2 / q1;
90 zl_factor = ZF0 / 4 / q1;
91 }
92
93
94 // adds effect of strip thickness
95 if( m_parameters[T_PRM] > 0 )
96 {
97 double d, se, We, ke, qe;
98 d = ( m_parameters[T_PRM] * 1.25 / M_PI )
99 * ( 1 + log( 4 * M_PI * m_parameters[PHYS_WIDTH_PRM] / m_parameters[T_PRM] ) );
100 se = m_parameters[PHYS_S_PRM] - d;
102
103 // modifies k1 accordingly (k1 = ke)
104 ke = We / ( We + se + se ); // ke = k1 + (1 - k1 * k1) * d / 2 / s;
105 qe = ellipk( ke ) / ellipk( sqrt( 1 - ke * ke ) );
106
107 // backside is metal
108 if( backMetal )
109 {
110 qz = 1 / ( qe + q3 );
111 er0 = 1 + q3 * qz * ( m_parameters[EPSILONR_PRM] - 1 );
112 zl_factor = ZF0 / 2 * qz;
113 }
114 // backside is air
115 else
116 {
117 zl_factor = ZF0 / 4 / qe;
118 }
119
120 // modifies er0 as well
121 er0 = er0
122 - ( 0.7 * ( er0 - 1 ) * m_parameters[T_PRM] / m_parameters[PHYS_S_PRM] )
123 / ( q1 + ( 0.7 * m_parameters[T_PRM] / m_parameters[PHYS_S_PRM] ) );
124 }
125
126 // pre-compute square roots
127 double sr_er = sqrt( m_parameters[EPSILONR_PRM] );
128 double sr_er0 = sqrt( er0 );
129
130 // cut-off frequency of the TE0 mode
131 double fte = ( C0 / 4 ) / ( m_parameters[H_PRM] * sqrt( m_parameters[EPSILONR_PRM] - 1 ) );
132
133 // dispersion factor G
134 double p = log( m_parameters[PHYS_WIDTH_PRM] / m_parameters[H_PRM] );
135 double u = 0.54 - ( 0.64 - 0.015 * p ) * p;
136 double v = 0.43 - ( 0.86 - 0.54 * p ) * p;
137 double G = exp( u * log( m_parameters[PHYS_WIDTH_PRM] / m_parameters[PHYS_S_PRM] ) + v );
138
139 // loss constant factors (computed only once for efficiency's sake)
140 double ac = 0;
141
142 if( m_parameters[T_PRM] > 0 )
143 {
144 // equations by GHIONE
145 double n = ( 1 - k1 ) * 8 * M_PI / ( m_parameters[T_PRM] * ( 1 + k1 ) );
146 double a = m_parameters[PHYS_WIDTH_PRM] / 2;
147 double b = a + m_parameters[PHYS_S_PRM];
148 ac = ( M_PI + log( n * a ) ) / a + ( M_PI + log( n * b ) ) / b;
149 }
150
151 double ac_factor = ac / ( 4 * ZF0 * kk1 * kpk1 * ( 1 - k1 * k1 ) );
152 double ad_factor = ( m_parameters[EPSILONR_PRM] / ( m_parameters[EPSILONR_PRM] - 1 ) )
153 * m_parameters[TAND_PRM] * M_PI / C0;
154
155
156 // ....................................................
157 double sr_er_f = sr_er0;
158
159 // add the dispersive effects to er0
160 sr_er_f += ( sr_er - sr_er0 ) / ( 1 + G * pow( m_parameters[FREQUENCY_PRM] / fte, -1.8 ) );
161
162 // for now, the loss are limited to strip losses (no radiation
163 // losses yet) losses in neper/length
165 20.0 / log( 10.0 ) * m_parameters[PHYS_LEN_PRM] * ac_factor * sr_er0
166 * sqrt( M_PI * MU0 * m_parameters[FREQUENCY_PRM] / m_parameters[SIGMA_PRM] );
167 m_parameters[LOSS_DIELECTRIC_PRM] = 20.0 / log( 10.0 ) * m_parameters[PHYS_LEN_PRM] * ad_factor
168 * m_parameters[FREQUENCY_PRM] * ( sr_er_f * sr_er_f - 1 )
169 / sr_er_f;
170
171 m_parameters[ANG_L_PRM] = 2.0 * M_PI * m_parameters[PHYS_LEN_PRM] * sr_er_f
172 * m_parameters[FREQUENCY_PRM] / C0; /* in radians */
173
174 m_parameters[EPSILON_EFF_PRM] = sr_er_f * sr_er_f;
175 m_parameters[Z0_PRM] = zl_factor / sr_er_f;
176
178}
179
180
181// -------------------------------------------------------------------
183{
184
186 setResult( 1, unit_prop_delay, "ps/cm" );
189
191}
192
193
194#define MAX_ERROR 0.000001
195
196// -------------------------------------------------------------------
197/* @function calcSynthesize
198 *
199 * @TODO Add a warning in case the synthetizin algorithm did not converge.
200 * Add it for all transmission lines that uses @ref minimizeZ0Error1D .
201 */
203{
206 else
208}
209
210// -------------------------------------------------------------------
212{
215
216 if( isSelected( PHYS_S_PRM ) )
218
220
221 if( !std::isfinite( m_parameters[PHYS_S_PRM] ) || m_parameters[PHYS_S_PRM] <= 0 )
222 {
223 if( isSelected( PHYS_S_PRM ) )
225 else
227 }
228
229 if( !std::isfinite( m_parameters[PHYS_WIDTH_PRM] ) || m_parameters[PHYS_WIDTH_PRM] <= 0 )
230 {
233 else
235 }
236
237 if( !std::isfinite( m_parameters[PHYS_LEN_PRM] ) || m_parameters[PHYS_LEN_PRM] < 0 )
239
240 if( !std::isfinite( m_parameters[Z0_PRM] ) || m_parameters[Z0_PRM] < 0 )
242
243 if( !std::isfinite( m_parameters[ANG_L_PRM] ) || m_parameters[ANG_L_PRM] < 0 )
245}
246
247
249{
252
253 if( !std::isfinite( m_parameters[PHYS_S_PRM] ) || m_parameters[PHYS_S_PRM] <= 0 )
255
256 if( !std::isfinite( m_parameters[PHYS_WIDTH_PRM] ) || m_parameters[PHYS_WIDTH_PRM] <= 0 )
258
259 if( !std::isfinite( m_parameters[PHYS_LEN_PRM] ) || m_parameters[PHYS_LEN_PRM] < 0 )
261
262 if( !std::isfinite( m_parameters[Z0_PRM] ) || m_parameters[Z0_PRM] < 0 )
264
265 if( !std::isfinite( m_parameters[ANG_L_PRM] ) || m_parameters[ANG_L_PRM] < 0 )
267}
double unit_prop_delay
Definition: coplanar.h:40
void showAnalyze() override
Shows synthesis results and checks for errors / warnings.
Definition: coplanar.cpp:248
void show_results() override
Shows results.
Definition: coplanar.cpp:182
void calcAnalyze() override
Computation for analysis.
Definition: coplanar.cpp:51
bool backMetal
Definition: coplanar.h:39
void calcSynthesize() override
Computation for synthesis.
Definition: coplanar.cpp:202
COPLANAR()
Definition: coplanar.cpp:34
void showSynthesize() override
Shows analysis results and checks for errors / warnings.
Definition: coplanar.cpp:211
bool isSelected(enum PRMS_ID aPrmId)
Definition: transline.cpp:116
double ellipk(double)
Definition: transline.cpp:321
static double calcUnitPropagationDelay(double epsilonEff)
Calculates the unit propagation delay (in ps/cm) for the given effective dielectric constant.
Definition: transline.cpp:443
void Init()
Definition: transline.cpp:87
void setResult(int, double, const char *)
Definition: transline.cpp:130
bool minimizeZ0Error1D(double *)
@function minimizeZ0Error1D
Definition: transline.cpp:346
double m_parameters[EXTRA_PRMS_COUNT]
Definition: transline.h:133
const char * m_Name
Definition: transline.h:86
void setProperty(enum PRMS_ID aPrmId, double aValue)
Definition: transline.cpp:106
double skin_depth()
@function skin_depth calculate skin depth
Definition: transline.cpp:234
void setErrorLevel(PRMS_ID, char)
@function setErrorLevel
Definition: transline.cpp:432
#define G(x, y, z)
Definition: md5_hash.cpp:16
#define UNIT_MICRON
@ LOSS_DIELECTRIC_PRM
Definition: transline.h:73
@ EPSILON_EFF_PRM
Definition: transline.h:76
@ LOSS_CONDUCTOR_PRM
Definition: transline.h:74
@ SIGMA_PRM
Definition: transline.h:71
@ SKIN_DEPTH_PRM
Definition: transline.h:72
@ FREQUENCY_PRM
Definition: transline.h:53
@ T_PRM
Definition: transline.h:48
@ Z0_PRM
Definition: transline.h:54
@ TAND_PRM
Definition: transline.h:42
@ PHYS_LEN_PRM
Definition: transline.h:62
@ ANG_L_PRM
Definition: transline.h:57
@ EPSILONR_PRM
Definition: transline.h:41
@ PHYS_S_PRM
Definition: transline.h:60
@ H_PRM
Definition: transline.h:44
@ PHYS_WIDTH_PRM
Definition: transline.h:58
#define TRANSLINE_WARNING
Definition: transline.h:32
#define TRANSLINE_ERROR
Definition: transline.h:33