KiCad PCB EDA Suite
Loading...
Searching...
No Matches
common/transline_calculations/microstrip.cpp
Go to the documentation of this file.
1/*
2 * Copyright (C) 2001 Gopal Narayanan <[email protected]>
3 * Copyright (C) 2002 Claudio Girardi <[email protected]>
4 * Copyright (C) 2005, 2006 Stefan Jahn <[email protected]>
5 * Modified for Kicad: 2018 Jean-Pierre Charras <jp.charras at wanadoo.fr>
6 * Copyright The KiCad Developers, see AUTHORS.txt for contributors.
7 *
8 * This program is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU General Public License
10 * as published by the Free Software Foundation; either version 2
11 * of the License, or (at your option) any later version.
12 *
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU 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
26
27
28namespace TC = TRANSLINE_CALCULATIONS;
30
31
33{
34 // Effective permeability
35 mur_eff_ms();
36
37 // Static impedance
39
40 // Calculate freq dependence of er and Z0
41 dispersion();
42
43 // Calculate electrical lengths
44 line_angle();
45
46 // Calculate losses
48}
49
50
52{
53 const double z0_dest = GetParameter( TCP::Z0 );
54 const double angl_dest = GetParameter( TCP::ANG_L );
55
56 // Calculate width and use for initial value in Newton's method
57 SetParameter( TCP::PHYS_WIDTH, SynthesizeWidth() );
58
59 // Optimise Z0, varying width
60 if( !MinimiseZ0Error1D( TCP::PHYS_WIDTH, TCP::Z0 ) )
61 return false;
62
63 // Re-calculate with required output parameters
64 SetParameter( TCP::Z0, z0_dest );
65 SetParameter( TCP::ANG_L, angl_dest );
66 double const er_eff = GetParameter( TCP::EPSILON_EFF );
67 SetParameter( TCP::PHYS_LEN, TC::C0 / GetParameter( TCP::FREQUENCY ) / sqrt( er_eff * mur_eff )
68 * GetParameter( TCP::ANG_L ) / 2.0 / M_PI ); /* in m */
69 Analyse();
70
71 // Set the output parameters
72 SetParameter( TCP::Z0, z0_dest );
73 SetParameter( TCP::ANG_L, angl_dest );
74 SetParameter( TCP::PHYS_LEN, TC::C0 / GetParameter( TCP::FREQUENCY ) / sqrt( er_eff * mur_eff )
75 * GetParameter( TCP::ANG_L ) / 2.0 / M_PI ); /* in m */
76
77 return true;
78}
79
80
82{
83 SetAnalysisResult( TCP::EPSILON_EFF, GetParameter( TCP::EPSILON_EFF ) );
84 SetAnalysisResult( TCP::UNIT_PROP_DELAY, GetParameter( TCP::UNIT_PROP_DELAY ) );
85 SetAnalysisResult( TCP::ATTEN_COND, GetParameter( TCP::ATTEN_COND ) );
86 SetAnalysisResult( TCP::ATTEN_DILECTRIC, GetParameter( TCP::ATTEN_DILECTRIC ) );
87 SetAnalysisResult( TCP::SKIN_DEPTH, GetParameter( TCP::SKIN_DEPTH ) );
88
89 const double Z0 = GetParameter( TCP::Z0 );
90 const double ANG_L = GetParameter( TCP::ANG_L );
91 const double L = GetParameter( TCP::PHYS_LEN );
92 const double W = GetParameter( TCP::PHYS_WIDTH );
93
94 const bool Z0_invalid = !std::isfinite( Z0 ) || Z0 < 0;
95 const bool ANG_L_invalid = !std::isfinite( ANG_L ) || ANG_L < 0;
96 const bool L_invalid = !std::isfinite( L ) || L < 0;
97 const bool W_invalid = !std::isfinite( W ) || W <= 0;
98
99 SetAnalysisResult( TCP::Z0, Z0, Z0_invalid ? TRANSLINE_STATUS::TS_ERROR : TRANSLINE_STATUS::OK );
100 SetAnalysisResult( TCP::ANG_L, ANG_L, ANG_L_invalid ? TRANSLINE_STATUS::TS_ERROR : TRANSLINE_STATUS::OK );
101 SetAnalysisResult( TCP::PHYS_LEN, L, L_invalid ? TRANSLINE_STATUS::WARNING : TRANSLINE_STATUS::OK );
102 SetAnalysisResult( TCP::PHYS_WIDTH, W, W_invalid ? TRANSLINE_STATUS::WARNING : TRANSLINE_STATUS::OK );
103}
104
105
107{
108 SetSynthesisResult( TCP::EPSILON_EFF, GetParameter( TCP::EPSILON_EFF ) );
109 SetSynthesisResult( TCP::UNIT_PROP_DELAY, GetParameter( TCP::UNIT_PROP_DELAY ) );
110 SetSynthesisResult( TCP::ATTEN_COND, GetParameter( TCP::ATTEN_COND ) );
111 SetSynthesisResult( TCP::ATTEN_DILECTRIC, GetParameter( TCP::ATTEN_DILECTRIC ) );
112 SetSynthesisResult( TCP::SKIN_DEPTH, GetParameter( TCP::SKIN_DEPTH ) );
113
114 const double Z0 = GetParameter( TCP::Z0 );
115 const double ANG_L = GetParameter( TCP::ANG_L );
116 const double L = GetParameter( TCP::PHYS_LEN );
117 const double W = GetParameter( TCP::PHYS_WIDTH );
118
119 const bool Z0_invalid = !std::isfinite( Z0 ) || Z0 < 0;
120 const bool ANG_L_invalid = !std::isfinite( ANG_L ) || ANG_L < 0;
121 const bool L_invalid = !std::isfinite( L ) || L < 0;
122 const bool W_invalid = !std::isfinite( W ) || W <= 0;
123
124 SetSynthesisResult( TCP::Z0, Z0, Z0_invalid ? TRANSLINE_STATUS::WARNING : TRANSLINE_STATUS::OK );
125 SetSynthesisResult( TCP::ANG_L, ANG_L, ANG_L_invalid ? TRANSLINE_STATUS::WARNING : TRANSLINE_STATUS::OK );
126 SetSynthesisResult( TCP::PHYS_LEN, L, L_invalid ? TRANSLINE_STATUS::TS_ERROR : TRANSLINE_STATUS::OK );
127 SetSynthesisResult( TCP::PHYS_WIDTH, W, W_invalid ? TRANSLINE_STATUS::TS_ERROR : TRANSLINE_STATUS::OK );
128}
129
130
132{
133 const double e_r = GetParameter( TCP::EPSILONR );
134 const double a = ( ( GetParameter( TCP::Z0 ) / TC::ZF0 / 2 / M_PI ) * sqrt( ( e_r + 1 ) / 2. ) )
135 + ( ( e_r - 1 ) / ( e_r + 1 ) * ( 0.23 + ( 0.11 / e_r ) ) );
136 const double b = TC::ZF0 / 2 * M_PI / ( GetParameter( TCP::Z0 ) * sqrt( e_r ) );
137
138 double w_h;
139
140 if( a > 1.52 )
141 {
142 w_h = 8 * exp( a ) / ( exp( 2. * a ) - 2 );
143 }
144 else
145 {
146 w_h = ( 2. / M_PI )
147 * ( b - 1. - log( ( 2 * b ) - 1. )
148 + ( ( e_r - 1 ) / ( 2 * e_r ) ) * ( log( b - 1. ) + 0.39 - 0.61 / e_r ) );
149 }
150
151 double width;
152
153 if( GetParameter( TCP::H ) > 0.0 )
154 width = w_h * GetParameter( TCP::H );
155 else
156 width = 0;
157
158 return width;
159}
160
161
162double MICROSTRIP::Z0_dispersion( double u, double e_r, double e_r_eff_0, double e_r_eff_f, double f_n )
163{
164 const double R_1 = 0.03891 * pow( e_r, 1.4 );
165 const double R_2 = 0.267 * pow( u, 7.0 );
166 const double R_3 = 4.766 * exp( -3.228 * pow( u, 0.641 ) );
167 const double R_4 = 0.016 + pow( 0.0514 * e_r, 4.524 );
168 const double R_5 = pow( f_n / 28.843, 12.0 );
169 const double R_6 = 22.2 * pow( u, 1.92 );
170 const double R_7 = 1.206 - 0.3144 * exp( -R_1 ) * ( 1.0 - exp( -R_2 ) );
171 const double R_8 = 1.0 + 1.275 * ( 1.0 - exp( -0.004625 * R_3 * pow( e_r, 1.674 ) * pow( f_n / 18.365, 2.745 ) ) );
172 double tmpf = pow( e_r - 1.0, 6.0 );
173 const double R_9 = 5.086 * R_4 * ( R_5 / ( 0.3838 + 0.386 * R_4 ) ) * ( exp( -R_6 ) / ( 1.0 + 1.2992 * R_5 ) )
174 * ( tmpf / ( 1.0 + 10.0 * tmpf ) );
175 const double R_10 = 0.00044 * pow( e_r, 2.136 ) + 0.0184;
176 tmpf = pow( f_n / 19.47, 6.0 );
177 const double R_11 = tmpf / ( 1.0 + 0.0962 * tmpf );
178 const double R_12 = 1.0 / ( 1.0 + 0.00245 * u * u );
179 const double R_13 = 0.9408 * pow( e_r_eff_f, R_8 ) - 0.9603;
180 const double R_14 = ( 0.9408 - R_9 ) * pow( e_r_eff_0, R_8 ) - 0.9603;
181 const double R_15 = 0.707 * R_10 * pow( f_n / 12.3, 1.097 );
182 const double R_16 = 1.0 + 0.0503 * e_r * e_r * R_11 * ( 1.0 - exp( -pow( u / 15.0, 6.0 ) ) );
183 const double R_17 = R_7 * ( 1.0 - 1.1241 * ( R_12 / R_16 ) * exp( -0.026 * pow( f_n, 1.15656 ) - R_15 ) );
184
185 return pow( R_13 / R_14, R_17 );
186}
187
188
190{
191 const double freq = 6.0 + ( 2.0 * M_PI - 6.0 ) * exp( -pow( 30.666 / u, 0.7528 ) );
192 return ( TC::ZF0 / ( 2.0 * M_PI ) ) * log( freq / u + sqrt( 1.0 + 4.0 / ( u * u ) ) );
193}
194
195
196double MICROSTRIP::delta_Z0_cover( double u, double h2h )
197{
198 const double h2hp1 = 1.0 + h2h;
199 const double P = 270.0 * ( 1.0 - tanh( 1.192 + 0.706 * sqrt( h2hp1 ) - 1.389 / h2hp1 ) );
200 const double Q = 1.0109 - atanh( ( 0.012 * u + 0.177 * u * u - 0.027 * u * u * u ) / ( h2hp1 * h2hp1 ) );
201 return P * Q;
202}
203
204
205double MICROSTRIP::filling_factor( double u, double e_r )
206{
207 const double u2 = u * u;
208 const double u3 = u2 * u;
209 const double u4 = u3 * u;
210 const double a = 1.0 + log( ( u4 + u2 / 2704 ) / ( u4 + 0.432 ) ) / 49.0 + log( 1.0 + u3 / 5929.741 ) / 18.7;
211 const double b = 0.564 * pow( ( e_r - 0.9 ) / ( e_r + 3.0 ), 0.053 );
212 return pow( 1.0 + 10.0 / u, -a * b );
213}
214
215
216double MICROSTRIP::delta_q_cover( double h2h )
217{
218 return tanh( 1.043 + 0.121 * h2h - 1.164 / h2h );
219}
220
221
222double MICROSTRIP::delta_q_thickness( double u, double t_h )
223{
224 return ( 2.0 * log( 2.0 ) / M_PI ) * ( t_h / sqrt( u ) );
225}
226
227
228double MICROSTRIP::e_r_effective( double e_r, double q )
229{
230 return 0.5 * ( e_r + 1.0 ) + 0.5 * q * ( e_r - 1.0 );
231}
232
233
234double MICROSTRIP::delta_u_thickness( double u, double t_h, double e_r )
235{
236 double delta_u;
237
238 if( t_h > 0.0 )
239 {
240 /* correction for thickness for a homogeneous microstrip */
241 delta_u = ( t_h / M_PI ) * log( 1.0 + ( 4.0 * M_E ) * pow( tanh( sqrt( 6.517 * u ) ), 2.0 ) / t_h );
242 /* correction for strip on a substrate with relative permettivity e_r */
243 delta_u = 0.5 * delta_u * ( 1.0 + 1.0 / cosh( sqrt( e_r - 1.0 ) ) );
244 }
245 else
246 {
247 delta_u = 0.0;
248 }
249 return delta_u;
250}
251
252
253double MICROSTRIP::e_r_dispersion( double u, double e_r, double f_n )
254{
255 const double P_1 =
256 0.27488 + u * ( 0.6315 + 0.525 / pow( 1.0 + 0.0157 * f_n, 20.0 ) ) - 0.065683 * exp( -8.7513 * u );
257 const double P_2 = 0.33622 * ( 1.0 - exp( -0.03442 * e_r ) );
258 const double P_3 = 0.0363 * exp( -4.6 * u ) * ( 1.0 - exp( -pow( f_n / 38.7, 4.97 ) ) );
259 const double P_4 = 1.0 + 2.751 * ( 1.0 - exp( -pow( e_r / 15.916, 8.0 ) ) );
260
261 return P_1 * P_2 * pow( ( P_3 * P_4 + 0.1844 ) * f_n, 1.5763 );
262}
263
264
266{
267 double alpha_c;
268 const double e_r_eff_0 = er_eff_0;
269 const double delta = GetParameter( TCP::SKIN_DEPTH );
270
271 if( GetParameter( TCP::FREQUENCY ) > 0.0 )
272 {
273 /* current distribution factor */
274 const double K = exp( -1.2 * pow( Z0_h_1 / TC::ZF0, 0.7 ) );
275 /* skin resistance */
276 double R_s = 1.0 / ( GetParameter( TCP::SIGMA ) * delta );
277
278 /* correction for surface roughness */
279 R_s *= 1.0 + ( ( 2.0 / M_PI ) * atan( 1.40 * pow( ( GetParameter( TCP::ROUGH ) / delta ), 2.0 ) ) );
280 /* strip inductive quality factor */
281 const double Q_c = ( M_PI * Z0_h_1 * GetParameter( TCP::PHYS_WIDTH ) * GetParameter( TCP::FREQUENCY ) )
282 / ( R_s * TC::C0 * K );
283 alpha_c = ( 20.0 * M_PI / log( 10.0 ) ) * GetParameter( TCP::FREQUENCY ) * sqrt( e_r_eff_0 ) / ( TC::C0 * Q_c );
284 }
285 else
286 {
287 alpha_c = 0.0;
288 }
289
290 return alpha_c;
291}
292
293
295{
296 const double e_r = GetParameter( TCP::EPSILONR );
297 const double e_r_eff_0 = er_eff_0;
298
299 return ( 20.0 * M_PI / log( 10.0 ) ) * ( GetParameter( TCP::FREQUENCY ) / TC::C0 ) * ( e_r / sqrt( e_r_eff_0 ) )
300 * ( ( e_r_eff_0 - 1.0 ) / ( e_r - 1.0 ) ) * GetParameter( TCP::TAND );
301}
302
303
305{
306 const double e_r = GetParameter( TCP::EPSILONR );
307 const double h2 = GetParameter( TCP::H_T );
308 const double h2h = h2 / GetParameter( TCP::H );
309 double u = GetParameter( TCP::PHYS_WIDTH ) / GetParameter( TCP::H );
310 const double t_h = GetParameter( TCP::T ) / GetParameter( TCP::H );
311
312 /* compute normalized width correction for e_r = 1.0 */
313 const double delta_u_1 = delta_u_thickness( u, t_h, 1.0 );
314 /* compute homogeneous stripline impedance */
315 Z0_h_1 = Z0_homogeneous( u + delta_u_1 );
316 /* compute normalized width correction */
317 const double delta_u_r = delta_u_thickness( u, t_h, e_r );
318 u += delta_u_r;
319 /* compute homogeneous stripline impedance */
320 const double Z0_h_r = Z0_homogeneous( u );
321
322 /* filling factor, with width corrected for thickness */
323 const double q_inf = filling_factor( u, e_r );
324 /* cover effect */
325 const double q_c = delta_q_cover( h2h );
326 /* thickness effect */
327 const double q_t = delta_q_thickness( u, t_h );
328 /* resultant filling factor */
329 const double q = ( q_inf - q_t ) * q_c;
330
331 /* e_r corrected for thickness and non-homogeneous material */
332 const double e_r_eff_t = e_r_effective( e_r, q );
333
334 /* effective dielectric constant */
335 const double e_r_eff = e_r_eff_t * pow( Z0_h_1 / Z0_h_r, 2.0 );
336
337 /* characteristic impedance, corrected for thickness, cover */
338 /* and non-homogeneous material */
339 SetParameter( TCP::Z0, Z0_h_r / sqrt( e_r_eff_t ) );
340
341 w_eff = u * GetParameter( TCP::H );
342 er_eff_0 = e_r_eff;
343 Z0_0 = GetParameter( TCP::Z0 );
344}
345
346
348{
349 const double e_r = GetParameter( TCP::EPSILONR );
350 const double e_r_eff_0 = er_eff_0;
351 const double u = GetParameter( TCP::PHYS_WIDTH ) / GetParameter( TCP::H );
352
353 /* normalized frequency [GHz * mm] */
354 const double f_n = GetParameter( TCP::FREQUENCY ) * GetParameter( TCP::H ) / 1e06;
355
356 const double P = e_r_dispersion( u, e_r, f_n );
357 /* effective dielectric constant corrected for dispersion */
358 const double e_r_eff_f = e_r - ( e_r - e_r_eff_0 ) / ( 1.0 + P );
359
360 const double D = Z0_dispersion( u, e_r, e_r_eff_0, e_r_eff_f, f_n );
361 const double Z0_f = Z0_0 * D;
362
363 SetParameter( TCP::UNIT_PROP_DELAY, UnitPropagationDelay( e_r_eff_f ) );
364 SetParameter( TCP::EPSILON_EFF, e_r_eff_f );
365 SetParameter( TCP::Z0, Z0_f );
366}
367
368
370{
371 SetParameter( TCP::SKIN_DEPTH, SkinDepth() );
372 SetParameter( TCP::ATTEN_COND, conductor_losses() * GetParameter( TCP::PHYS_LEN ) );
373 SetParameter( TCP::ATTEN_DILECTRIC, dielectric_losses() * GetParameter( TCP::PHYS_LEN ) );
374}
375
376
378{
379 const double mur = GetParameter( TCP::MUR );
380 const double h = GetParameter( TCP::H );
381 const double w = GetParameter( TCP::PHYS_WIDTH );
382 mur_eff = ( 2.0 * mur ) / ( ( 1.0 + mur ) + ( ( 1.0 - mur ) * pow( ( 1.0 + ( 10.0 * h / w ) ), -0.5 ) ) );
383}
384
385
387{
388 double e_r_eff = GetParameter( TCP::EPSILON_EFF );
389
390 // Velocity
391 double v = TC::C0 / sqrt( e_r_eff * mur_eff );
392 // Wavelength
393 double lambda_g = v / GetParameter( TCP::FREQUENCY );
394 // Electrical angles (rad)
395 SetParameter( TCP::ANG_L, 2.0 * M_PI * GetParameter( TCP::PHYS_LEN ) / lambda_g );
396}
double w_eff
Effective width of line.
void microstrip_Z0()
Calculates the microstrip static impedance.
static double e_r_effective(double, double)
Calculates effective dielectric constant from material e_r and filling factor.
bool Synthesize(SYNTHESIZE_OPTS aOpts) override
Synthesis track geometry parameters to match given Z0.
double Z0_0
static characteristic impedance
void line_angle()
Calculates microstrip length in radians.
void Analyse() override
Analyse track geometry parameters to output Z0 and Ang_L.
static double Z0_dispersion(double, double, double, double, double)
Calculates the dispersion correction factor for the characteristic impedance static.
void dispersion()
Calculates frequency dependent parameters of the microstrip.
static double filling_factor(double, double)
Calculates the filling factor for a microstrip without cover and zero conductor thickness.
double SynthesizeWidth() const
Calculates the width with the current set of parameters.
static double e_r_dispersion(double, double, double)
Calculates the dispersion correction factor for the effective permeability.
static double delta_u_thickness(double, double, double)
Calculates the thickness effect on normalized width.
static double delta_q_thickness(double, double)
Calculates the thickness effect on filling factor.
static double delta_q_cover(double)
Calculates the cover effect on filling factor.
double mur_eff
Effective mag. permeability.
double er_eff_0
Static effective dielectric constant.
void mur_eff_ms()
Calculates the effective magnetic permeability.
void SetSynthesisResults() override
Sets the output values and status following synthesis.
void SetAnalysisResults() override
Sets the output values and status following analysis.
static double Z0_homogeneous(double)
Calculates the impedance for a stripline in a homogeneous medium, without cover effects.
double dielectric_losses() const
Calculates the microstrip dielectric losses per unit.
double Z0_h_1
homogeneous stripline impedance
void attenuation()
Calculates the attenuation of the microstrip.
static double delta_Z0_cover(double, double)
Calculates the cover effect on impedance for a stripline in a homogeneous medium.
double conductor_losses() const
Calculate the microstrip conductor losses per unit.
double GetParameter(const TRANSLINE_PARAMETERS aParam) const
Gets the given calculation property.
void SetParameter(const TRANSLINE_PARAMETERS aParam, const double aValue)
Sets the given calculation property.
void SetSynthesisResult(TRANSLINE_PARAMETERS aParam, const double aValue, const TRANSLINE_STATUS aStatus=TRANSLINE_STATUS::OK)
Sets a synthesis result.
bool MinimiseZ0Error1D(TRANSLINE_PARAMETERS aOptimise, TRANSLINE_PARAMETERS aMeasure)
minimizeZ0Error1D
double SkinDepth() const
Calculate skin depth.
void SetAnalysisResult(TRANSLINE_PARAMETERS aParam, const double aValue, const TRANSLINE_STATUS aStatus=TRANSLINE_STATUS::OK)
Sets an analysis result.
static double UnitPropagationDelay(double aEpsilonEff)
Calculates the unit propagation delay (ps/cm) for the given effective permittivity.
double atanh(double x)
#define D(x)
Definition: ptree.cpp:41
int delta
SYNTHESIZE_OPTS
Options for specifying synthesis inputs, targets, or strategies.
TRANSLINE_PARAMETERS
All possible parameters used (as inputs or outputs) by the transmission line calculations.