Refactor PCB calcs to common library, and add coupled stripline

Fixes https://gitlab.com/kicad/code/kicad/-/issues/16863
This commit is contained in:
JamesJCode 2025-04-20 23:52:34 +01:00
parent 2fd2fe6e2d
commit aac9731852
37 changed files with 5035 additions and 1676 deletions

View File

@ -557,6 +557,14 @@ set( COMMON_IO_SRCS
io/easyedapro/easyedapro_import_utils.cpp
)
set ( COMMON_TRANSLINE_CALCULATION_SRCS
transline_calculations/transline_calculation_base.cpp
transline_calculations/microstrip.cpp
transline_calculations/coupled_microstrip.cpp
transline_calculations/stripline.cpp
transline_calculations/coupled_stripline.cpp
)
set( COMMON_IMPORT_GFX_SRCS
import_gfx/graphics_import_mgr.cpp
import_gfx/graphics_importer.cpp
@ -591,6 +599,7 @@ set( COMMON_SRCS
${FONT_SRCS}
${COMMON_IMPORT_GFX_SRCS}
${COMMON_GIT_SRCS}
${COMMON_TRANSLINE_CALCULATION_SRCS}
base_screen.cpp
bin_mod.cpp
bitmap_base.cpp

View File

@ -4893,6 +4893,7 @@ void BuildBitmapInfo( std::unordered_map<BITMAPS, std::vector<BITMAP_INFO>>& aBi
aBitmapInfoCache[BITMAPS::color_code_tolerance].emplace_back( BITMAPS::color_code_tolerance, wxT( "color_code_tolerance.png" ), -1, wxT( "light" ) );
aBitmapInfoCache[BITMAPS::color_code_value].emplace_back( BITMAPS::color_code_value, wxT( "color_code_value.png" ), -1, wxT( "light" ) );
aBitmapInfoCache[BITMAPS::color_code_value_and_name].emplace_back( BITMAPS::color_code_value_and_name, wxT( "color_code_value_and_name.png" ), -1, wxT( "light" ) );
aBitmapInfoCache[BITMAPS::coupled_stripline].emplace_back( BITMAPS::coupled_stripline, wxT( "coupled_stripline.png" ), -1, wxT( "light" ) );
aBitmapInfoCache[BITMAPS::creepage_clearance].emplace_back( BITMAPS::creepage_clearance, wxT( "creepage_clearance.png" ), -1, wxT( "light" ) );
aBitmapInfoCache[BITMAPS::cpw].emplace_back( BITMAPS::cpw, wxT( "cpw.png" ), -1, wxT( "light" ) );
aBitmapInfoCache[BITMAPS::cpw_back].emplace_back( BITMAPS::cpw_back, wxT( "cpw_back.png" ), -1, wxT( "light" ) );
@ -4928,6 +4929,7 @@ void BuildBitmapInfo( std::unordered_map<BITMAPS, std::vector<BITMAP_INFO>>& aBi
aBitmapInfoCache[BITMAPS::color_code_tolerance].emplace_back( BITMAPS::color_code_tolerance, wxT( "color_code_tolerance_dark.png" ), -1, wxT( "dark" ) );
aBitmapInfoCache[BITMAPS::color_code_value].emplace_back( BITMAPS::color_code_value, wxT( "color_code_value_dark.png" ), -1, wxT( "dark" ) );
aBitmapInfoCache[BITMAPS::color_code_value_and_name].emplace_back( BITMAPS::color_code_value_and_name, wxT( "color_code_value_and_name_dark.png" ), -1, wxT( "dark" ) );
aBitmapInfoCache[BITMAPS::coupled_stripline].emplace_back( BITMAPS::coupled_stripline, wxT( "coupled_stripline_dark.png" ), -1, wxT( "dark" ) );
aBitmapInfoCache[BITMAPS::creepage_clearance].emplace_back( BITMAPS::creepage_clearance, wxT( "creepage_clearance_dark.png" ), -1, wxT( "dark" ) );
aBitmapInfoCache[BITMAPS::cpw].emplace_back( BITMAPS::cpw, wxT( "cpw_dark.png" ), -1, wxT( "dark" ) );
aBitmapInfoCache[BITMAPS::cpw_back].emplace_back( BITMAPS::cpw_back, wxT( "cpw_back_dark.png" ), -1, wxT( "dark" ) );

View File

@ -0,0 +1,823 @@
/*
* Copyright (C) 2001 Gopal Narayanan <gopal@astro.umass.edu>
* Copyright (C) 2002 Claudio Girardi <claudio.girardi@ieee.org>
* Copyright (C) 2005, 2006 Stefan Jahn <stefan@lkcc.org>
* Modified for Kicad: 2018 Jean-Pierre Charras <jp.charras at wanadoo.fr>
* Copyright The KiCad Developers, see AUTHORS.txt for contributors.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this package; see the file COPYING. If not, write to
* the Free Software Foundation, Inc., 51 Franklin Street - Fifth Floor,
* Boston, MA 02110-1301, USA.
*/
#include <transline_calculations/coupled_microstrip.h>
#include <transline_calculations/units.h>
namespace TC = TRANSLINE_CALCULATIONS;
using TCP = TRANSLINE_PARAMETERS;
void COUPLED_MICROSTRIP::Analyse()
{
// Compute thickness corrections
delta_u_thickness();
// Get effective dielectric constants
er_eff_static();
// Impedances for even- and odd-mode
Z0_even_odd();
// Calculate freq dependence of er_eff_e, er_eff_o
er_eff_freq();
// Calculate frequency dependence of Z0e, Z0o */
Z0_dispersion();
// Calculate losses
attenuation();
// Calculate electrical lengths
line_angle();
// Calculate diff impedance
diff_impedance();
}
bool COUPLED_MICROSTRIP::Synthesize( const SYNTHESIZE_OPTS aOpts )
{
if( aOpts == SYNTHESIZE_OPTS::FIX_WIDTH )
return MinimiseZ0Error1D( TCP::PHYS_S, TCP::Z0_O );
if( aOpts == SYNTHESIZE_OPTS::FIX_SPACING )
return MinimiseZ0Error1D( TCP::PHYS_WIDTH, TCP::Z0_O );
double Z0_e, Z0_o, ang_l_dest;
double f1, f2, ft1, ft2, j11, j12, j21, j22, d_s_h, d_w_h, err;
double eps = 1e-04;
double w_h, s_h, le, lo;
/* required value of Z0_e and Z0_o */
Z0_e = GetParameter( TCP::Z0_E );
Z0_o = GetParameter( TCP::Z0_O );
ang_l_e = GetParameter( TCP::ANG_L );
ang_l_o = GetParameter( TCP::ANG_L );
ang_l_dest = GetParameter( TCP::ANG_L );
/* calculate width and use for initial value in Newton's method */
synth_width();
w_h = GetParameter( TCP::PHYS_WIDTH ) / GetParameter( TCP::H );
s_h = GetParameter( TCP::PHYS_S ) / GetParameter( TCP::H );
f1 = f2 = 0;
int iters = 0;
/* rather crude Newton-Rhapson */
do
{
++iters;
/* compute Jacobian */
syn_fun( &ft1, &ft2, s_h + eps, w_h, Z0_e, Z0_o );
j11 = ( ft1 - f1 ) / eps;
j21 = ( ft2 - f2 ) / eps;
syn_fun( &ft1, &ft2, s_h, w_h + eps, Z0_e, Z0_o );
j12 = ( ft1 - f1 ) / eps;
j22 = ( ft2 - f2 ) / eps;
/* compute next step; increments of s_h and w_h */
d_s_h = ( -f1 * j22 + f2 * j12 ) / ( j11 * j22 - j21 * j12 );
d_w_h = ( -f2 * j11 + f1 * j21 ) / ( j11 * j22 - j21 * j12 );
s_h += d_s_h;
w_h += d_w_h;
/* compute the error with the new values of s_h and w_h */
syn_fun( &f1, &f2, s_h, w_h, Z0_e, Z0_o );
err = sqrt( f1 * f1 + f2 * f2 );
/* converged ? */
} while( err > 1e-04 && iters < 250 );
if( err > 1e-04 )
return false;
/* denormalize computed width and spacing */
SetParameter( TCP::PHYS_S, s_h * GetParameter( TCP::H ) );
SetParameter( TCP::PHYS_WIDTH, w_h * GetParameter( TCP::H ) );
/* calculate physical length */
le = TC::C0 / GetParameter( TCP::FREQUENCY ) / sqrt( er_eff_e ) * ang_l_dest / 2.0 / M_PI;
lo = TC::C0 / GetParameter( TCP::FREQUENCY ) / sqrt( er_eff_o ) * ang_l_dest / 2.0 / M_PI;
SetParameter( TCP::PHYS_LEN, sqrt( le * lo ) );
Analyse();
SetParameter( TCP::ANG_L, ang_l_dest );
SetParameter( TCP::Z0_E, Z0_e );
SetParameter( TCP::Z0_O, Z0_o );
return true;
}
void COUPLED_MICROSTRIP::SetAnalysisResults()
{
SetAnalysisResult( TCP::EPSILON_EFF_EVEN, er_eff_e );
SetAnalysisResult( TCP::EPSILON_EFF_ODD, er_eff_o );
SetAnalysisResult( TCP::UNIT_PROP_DELAY_EVEN, prop_delay_e );
SetAnalysisResult( TCP::UNIT_PROP_DELAY_ODD, prop_delay_o );
SetAnalysisResult( TCP::ATTEN_COND_EVEN, atten_cond_e );
SetAnalysisResult( TCP::ATTEN_COND_ODD, atten_cond_o );
SetAnalysisResult( TCP::ATTEN_DILECTRIC_EVEN, atten_dielectric_e );
SetAnalysisResult( TCP::ATTEN_DILECTRIC_ODD, atten_dielectric_o );
SetAnalysisResult( TCP::SKIN_DEPTH, GetParameter( TCP::SKIN_DEPTH ) );
SetAnalysisResult( TCP::Z_DIFF, Zdiff );
const double Z0_E = GetParameter( TCP::Z0_E );
const double Z0_O = GetParameter( TCP::Z0_O );
const double ANG_L = sqrt( ang_l_e * ang_l_o );
const double W = GetParameter( TCP::PHYS_WIDTH );
const double L = GetParameter( TCP::PHYS_LEN );
const double S = GetParameter( TCP::PHYS_S );
const bool Z0_E_invalid = !std::isfinite( Z0_E ) || Z0_E <= 0;
const bool Z0_O_invalid = !std::isfinite( Z0_O ) || Z0_O <= 0;
const bool ANG_L_invalid = !std::isfinite( ANG_L ) || ANG_L < 0;
const bool W_invalid = !std::isfinite( W ) || W <= 0;
const bool L_invalid = !std::isfinite( L ) || L < 0;
const bool S_invalid = !std::isfinite( S ) || S <= 0;
SetAnalysisResult( TCP::Z0_E, Z0_E, Z0_E_invalid ? TRANSLINE_STATUS::ERROR : TRANSLINE_STATUS::OK );
SetAnalysisResult( TCP::Z0_O, Z0_O, Z0_O_invalid ? TRANSLINE_STATUS::ERROR : TRANSLINE_STATUS::OK );
SetAnalysisResult( TCP::ANG_L, ANG_L, ANG_L_invalid ? TRANSLINE_STATUS::ERROR : TRANSLINE_STATUS::OK );
SetAnalysisResult( TCP::PHYS_WIDTH, W, W_invalid ? TRANSLINE_STATUS::WARNING : TRANSLINE_STATUS::OK );
SetAnalysisResult( TCP::PHYS_LEN, L, L_invalid ? TRANSLINE_STATUS::WARNING : TRANSLINE_STATUS::OK );
SetAnalysisResult( TCP::PHYS_S, S, S_invalid ? TRANSLINE_STATUS::WARNING : TRANSLINE_STATUS::OK );
}
void COUPLED_MICROSTRIP::SetSynthesisResults()
{
SetAnalysisResult( TCP::EPSILON_EFF_EVEN, er_eff_e );
SetAnalysisResult( TCP::EPSILON_EFF_ODD, er_eff_o );
SetAnalysisResult( TCP::UNIT_PROP_DELAY_EVEN, prop_delay_e );
SetAnalysisResult( TCP::UNIT_PROP_DELAY_ODD, prop_delay_o );
SetAnalysisResult( TCP::ATTEN_COND_EVEN, atten_cond_e );
SetAnalysisResult( TCP::ATTEN_COND_ODD, atten_cond_o );
SetAnalysisResult( TCP::ATTEN_DILECTRIC_EVEN, atten_dielectric_e );
SetAnalysisResult( TCP::ATTEN_DILECTRIC_ODD, atten_dielectric_o );
SetAnalysisResult( TCP::SKIN_DEPTH, GetParameter( TCP::SKIN_DEPTH ) );
SetAnalysisResult( TCP::Z_DIFF, Zdiff );
const double Z0_E = GetParameter( TCP::Z0_E );
const double Z0_O = GetParameter( TCP::Z0_O );
const double ANG_L = sqrt( ang_l_e * ang_l_o );
const double W = GetParameter( TCP::PHYS_WIDTH );
const double L = GetParameter( TCP::PHYS_LEN );
const double S = GetParameter( TCP::PHYS_S );
const bool Z0_E_invalid = !std::isfinite( Z0_E ) || Z0_E <= 0;
const bool Z0_O_invalid = !std::isfinite( Z0_O ) || Z0_O <= 0;
const bool ANG_L_invalid = !std::isfinite( ANG_L ) || ANG_L < 0;
const bool W_invalid = !std::isfinite( W ) || W <= 0;
const bool L_invalid = !std::isfinite( L ) || L < 0;
const bool S_invalid = !std::isfinite( S ) || S <= 0;
SetAnalysisResult( TCP::Z0_E, Z0_E, Z0_E_invalid ? TRANSLINE_STATUS::WARNING : TRANSLINE_STATUS::OK );
SetAnalysisResult( TCP::Z0_O, Z0_O, Z0_O_invalid ? TRANSLINE_STATUS::WARNING : TRANSLINE_STATUS::OK );
SetAnalysisResult( TCP::ANG_L, ANG_L, ANG_L_invalid ? TRANSLINE_STATUS::WARNING : TRANSLINE_STATUS::OK );
SetAnalysisResult( TCP::PHYS_WIDTH, W, W_invalid ? TRANSLINE_STATUS::ERROR : TRANSLINE_STATUS::OK );
SetAnalysisResult( TCP::PHYS_LEN, L, L_invalid ? TRANSLINE_STATUS::ERROR : TRANSLINE_STATUS::OK );
SetAnalysisResult( TCP::PHYS_S, S, S_invalid ? TRANSLINE_STATUS::ERROR : TRANSLINE_STATUS::OK );
}
double COUPLED_MICROSTRIP::delta_u_thickness_single( double u, double t_h )
{
double delta_u;
if( t_h > 0.0 )
{
delta_u = ( 1.25 * t_h / M_PI )
* ( 1.0
+ log( ( 2.0 + ( 4.0 * M_PI * u - 2.0 ) / ( 1.0 + exp( -100.0 * ( u - 1.0 / ( 2.0 * M_PI ) ) ) ) )
/ t_h ) );
}
else
{
delta_u = 0.0;
}
return delta_u;
}
/*
* delta_u_thickness() - compute the thickness effect on normalized
* width for coupled microstrips
*
* References: Rolf Jansen, "High-Speed Computation of Single and
* Coupled Microstrip Parameters Including Dispersion, High-Order
* Modes, Loss and Finite Strip Thickness", IEEE Trans. MTT, vol. 26,
* no. 2, pp. 75-82, Feb. 1978
*/
void COUPLED_MICROSTRIP::delta_u_thickness()
{
double e_r, u, g, t_h;
double delta_u, delta_t, delta_u_e, delta_u_o;
e_r = GetParameter( TCP::EPSILONR );
u = GetParameter( TCP::PHYS_WIDTH ) / GetParameter( TCP::H ); /* normalized line width */
g = GetParameter( TCP::PHYS_S ) / GetParameter( TCP::H ); /* normalized line spacing */
t_h = GetParameter( TCP::T ) / GetParameter( TCP::H ); /* normalized strip thickness */
if( t_h > 0.0 )
{
/* single microstrip correction for finite strip thickness */
delta_u = delta_u_thickness_single( u, t_h );
delta_t = t_h / ( g * e_r );
/* thickness correction for the even- and odd-mode */
delta_u_e = delta_u * ( 1.0 - 0.5 * exp( -0.69 * delta_u / delta_t ) );
delta_u_o = delta_u_e + delta_t;
}
else
{
delta_u_e = delta_u_o = 0.0;
}
w_t_e = GetParameter( TCP::PHYS_WIDTH ) + delta_u_e * GetParameter( TCP::H );
w_t_o = GetParameter( TCP::PHYS_WIDTH ) + delta_u_o * GetParameter( TCP::H );
}
void COUPLED_MICROSTRIP::compute_single_line()
{
/* prepare parameters for single microstrip computations */
m_aux_microstrip.SetParameter( TCP::EPSILONR, GetParameter( TCP::EPSILONR ) );
m_aux_microstrip.SetParameter( TCP::PHYS_WIDTH, GetParameter( TCP::PHYS_WIDTH ) );
m_aux_microstrip.SetParameter( TCP::H, GetParameter( TCP::H ) );
m_aux_microstrip.SetParameter( TCP::T, 0.0 );
//m_aux_microstrip.m_parameters[H_T ) = m_parameters[H_T );
m_aux_microstrip.SetParameter( TCP::H_T, 1e12 ); /* arbitrarily high */
m_aux_microstrip.SetParameter( TCP::FREQUENCY, GetParameter( TCP::FREQUENCY ) );
m_aux_microstrip.SetParameter( TCP::MURC, GetParameter( TCP::MURC ) );
m_aux_microstrip.microstrip_Z0();
m_aux_microstrip.dispersion();
}
double COUPLED_MICROSTRIP::filling_factor_even( double u, double g, double e_r )
{
double v, v3, v4, a_e, b_e, q_inf;
v = u * ( 20.0 + g * g ) / ( 10.0 + g * g ) + g * exp( -g );
v3 = v * v * v;
v4 = v3 * v;
a_e = 1.0 + log( ( v4 + v * v / 2704.0 ) / ( v4 + 0.432 ) ) / 49.0 + log( 1.0 + v3 / 5929.741 ) / 18.7;
b_e = 0.564 * pow( ( ( e_r - 0.9 ) / ( e_r + 3.0 ) ), 0.053 );
/* filling factor, with width corrected for thickness */
q_inf = pow( ( 1.0 + 10.0 / v ), -a_e * b_e );
return q_inf;
}
double COUPLED_MICROSTRIP::filling_factor_odd( double u, double g, double e_r )
{
double b_odd = 0.747 * e_r / ( 0.15 + e_r );
double c_odd = b_odd - ( b_odd - 0.207 ) * exp( -0.414 * u );
double d_odd = 0.593 + 0.694 * exp( -0.562 * u );
/* filling factor, with width corrected for thickness */
double q_inf = exp( -c_odd * pow( g, d_odd ) );
return q_inf;
}
double COUPLED_MICROSTRIP::delta_q_cover_even( double h2h )
{
double q_c;
if( h2h <= 39 )
q_c = tanh( 1.626 + 0.107 * h2h - 1.733 / sqrt( h2h ) );
else
q_c = 1.0;
return q_c;
}
double COUPLED_MICROSTRIP::delta_q_cover_odd( double h2h )
{
double q_c;
if( h2h <= 7 )
q_c = tanh( 9.575 / ( 7.0 - h2h ) - 2.965 + 1.68 * h2h - 0.311 * h2h * h2h );
else
q_c = 1.0;
return q_c;
}
void COUPLED_MICROSTRIP::er_eff_static()
{
double u_t_e, u_t_o, g, h2, h2h;
double a_o, t_h, q, q_c, q_t, q_inf;
double er_eff_single;
double er;
er = GetParameter( TCP::EPSILONR );
/* compute zero-thickness single line parameters */
compute_single_line();
er_eff_single = m_aux_microstrip.er_eff_0;
h2 = GetParameter( TCP::H_T );
u_t_e = w_t_e / GetParameter( TCP::H ); /* normalized even_mode line width */
u_t_o = w_t_o / GetParameter( TCP::H ); /* normalized odd_mode line width */
g = GetParameter( TCP::PHYS_S ) / GetParameter( TCP::H ); /* normalized line spacing */
h2h = h2 / GetParameter( TCP::H ); /* normalized cover height */
t_h = GetParameter( TCP::T ) / GetParameter( TCP::H ); /* normalized strip thickness */
/* filling factor, computed with thickness corrected width */
q_inf = filling_factor_even( u_t_e, g, er );
/* cover effect */
q_c = delta_q_cover_even( h2h );
/* thickness effect */
q_t = m_aux_microstrip.delta_q_thickness( u_t_e, t_h );
/* resultant filling factor */
q = ( q_inf - q_t ) * q_c;
/* static even-mode effective dielectric constant */
er_eff_e_0 = 0.5 * ( er + 1.0 ) + 0.5 * ( er - 1.0 ) * q;
/* filling factor, with width corrected for thickness */
q_inf = filling_factor_odd( u_t_o, g, er );
/* cover effect */
q_c = delta_q_cover_odd( h2h );
/* thickness effect */
q_t = m_aux_microstrip.delta_q_thickness( u_t_o, t_h );
/* resultant filling factor */
q = ( q_inf - q_t ) * q_c;
a_o = 0.7287 * ( er_eff_single - 0.5 * ( er + 1.0 ) ) * ( 1.0 - exp( -0.179 * u_t_o ) );
/* static odd-mode effective dielectric constant */
er_eff_o_0 = ( 0.5 * ( er + 1.0 ) + a_o - er_eff_single ) * q + er_eff_single;
}
double COUPLED_MICROSTRIP::delta_Z0_even_cover( double g, double u, double h2h )
{
double f_e, g_e, delta_Z0_even;
double x, y, A, B, C, D, E, F;
A = -4.351 / pow( 1.0 + h2h, 1.842 );
B = 6.639 / pow( 1.0 + h2h, 1.861 );
C = -2.291 / pow( 1.0 + h2h, 1.90 );
f_e = 1.0 - atanh( A + ( B + C * u ) * u );
x = pow( 10.0, 0.103 * g - 0.159 );
y = pow( 10.0, 0.0492 * g - 0.073 );
D = 0.747 / sin( 0.5 * M_PI * x );
E = 0.725 * sin( 0.5 * M_PI * y );
F = pow( 10.0, 0.11 - 0.0947 * g );
g_e = 270.0 * ( 1.0 - tanh( D + E * sqrt( 1.0 + h2h ) - F / ( 1.0 + h2h ) ) );
delta_Z0_even = f_e * g_e;
return delta_Z0_even;
}
double COUPLED_MICROSTRIP::delta_Z0_odd_cover( double g, double u, double h2h )
{
double f_o, g_o, delta_Z0_odd;
double G, J, K, L;
J = tanh( pow( 1.0 + h2h, 1.585 ) / 6.0 );
f_o = pow( u, J );
G = 2.178 - 0.796 * g;
if( g > 0.858 )
K = log10( 20.492 * pow( g, 0.174 ) );
else
K = 1.30;
if( g > 0.873 )
L = 2.51 * pow( g, -0.462 );
else
L = 2.674;
g_o = 270.0 * ( 1.0 - tanh( G + K * sqrt( 1.0 + h2h ) - L / ( 1.0 + h2h ) ) );
delta_Z0_odd = f_o * g_o;
return delta_Z0_odd;
}
void COUPLED_MICROSTRIP::Z0_even_odd()
{
double er_eff, h2, u_t_e, u_t_o, g, h2h;
double Q_1, Q_2, Q_3, Q_4, Q_5, Q_6, Q_7, Q_8, Q_9, Q_10;
double delta_Z0_e_0, delta_Z0_o_0, Z0_single, er_eff_single;
h2 = GetParameter( TCP::H_T );
u_t_e = w_t_e / GetParameter( TCP::H ); /* normalized even-mode line width */
u_t_o = w_t_o / GetParameter( TCP::H ); /* normalized odd-mode line width */
g = GetParameter( TCP::PHYS_S ) / GetParameter( TCP::H ); /* normalized line spacing */
h2h = h2 / GetParameter( TCP::H ); /* normalized cover height */
Z0_single = m_aux_microstrip.Z0_0;
er_eff_single = m_aux_microstrip.er_eff_0;
/* even-mode */
er_eff = er_eff_e_0;
Q_1 = 0.8695 * pow( u_t_e, 0.194 );
Q_2 = 1.0 + 0.7519 * g + 0.189 * pow( g, 2.31 );
Q_3 = 0.1975 + pow( ( 16.6 + pow( ( 8.4 / g ), 6.0 ) ), -0.387 )
+ log( pow( g, 10.0 ) / ( 1.0 + pow( g / 3.4, 10.0 ) ) ) / 241.0;
Q_4 = 2.0 * Q_1 / ( Q_2 * ( exp( -g ) * pow( u_t_e, Q_3 ) + ( 2.0 - exp( -g ) ) * pow( u_t_e, -Q_3 ) ) );
/* static even-mode impedance */
Z0_e_0 = Z0_single * sqrt( er_eff_single / er_eff ) / ( 1.0 - sqrt( er_eff_single ) * Q_4 * Z0_single / TC::ZF0 );
/* correction for cover */
delta_Z0_e_0 = delta_Z0_even_cover( g, u_t_e, h2h ) / sqrt( er_eff );
Z0_e_0 = Z0_e_0 - delta_Z0_e_0;
/* odd-mode */
er_eff = er_eff_o_0;
Q_5 = 1.794 + 1.14 * log( 1.0 + 0.638 / ( g + 0.517 * pow( g, 2.43 ) ) );
Q_6 = 0.2305 + log( pow( g, 10.0 ) / ( 1.0 + pow( g / 5.8, 10.0 ) ) ) / 281.3
+ log( 1.0 + 0.598 * pow( g, 1.154 ) ) / 5.1;
Q_7 = ( 10.0 + 190.0 * g * g ) / ( 1.0 + 82.3 * g * g * g );
Q_8 = exp( -6.5 - 0.95 * log( g ) - pow( g / 0.15, 5.0 ) );
Q_9 = log( Q_7 ) * ( Q_8 + 1.0 / 16.5 );
Q_10 = ( Q_2 * Q_4 - Q_5 * exp( log( u_t_o ) * Q_6 * pow( u_t_o, -Q_9 ) ) ) / Q_2;
/* static odd-mode impedance */
Z0_o_0 = Z0_single * sqrt( er_eff_single / er_eff ) / ( 1.0 - sqrt( er_eff_single ) * Q_10 * Z0_single / TC::ZF0 );
/* correction for cover */
delta_Z0_o_0 = delta_Z0_odd_cover( g, u_t_o, h2h ) / sqrt( er_eff );
Z0_o_0 = Z0_o_0 - delta_Z0_o_0;
}
void COUPLED_MICROSTRIP::er_eff_freq()
{
double P_1, P_2, P_3, P_4, P_5, P_6, P_7;
double P_8, P_9, P_10, P_11, P_12, P_13, P_14, P_15;
double F_e, F_o;
double er_eff, u, g, f_n;
u = GetParameter( TCP::PHYS_WIDTH ) / GetParameter( TCP::H ); /* normalize line width */
g = GetParameter( TCP::PHYS_S ) / GetParameter( TCP::H ); /* normalize line spacing */
/* normalized frequency [GHz * mm] */
f_n = GetParameter( TCP::FREQUENCY ) * GetParameter( TCP::H ) / 1e06;
er_eff = er_eff_e_0;
P_1 = 0.27488 + ( 0.6315 + 0.525 / pow( 1.0 + 0.0157 * f_n, 20.0 ) ) * u - 0.065683 * exp( -8.7513 * u );
P_2 = 0.33622 * ( 1.0 - exp( -0.03442 * GetParameter( TCP::EPSILONR ) ) );
P_3 = 0.0363 * exp( -4.6 * u ) * ( 1.0 - exp( -pow( f_n / 38.7, 4.97 ) ) );
P_4 = 1.0 + 2.751 * ( 1.0 - exp( -pow( GetParameter( TCP::EPSILONR ) / 15.916, 8.0 ) ) );
P_5 = 0.334 * exp( -3.3 * pow( GetParameter( TCP::EPSILONR ) / 15.0, 3.0 ) ) + 0.746;
P_6 = P_5 * exp( -pow( f_n / 18.0, 0.368 ) );
P_7 = 1.0 + 4.069 * P_6 * pow( g, 0.479 ) * exp( -1.347 * pow( g, 0.595 ) - 0.17 * pow( g, 2.5 ) );
F_e = P_1 * P_2 * pow( ( P_3 * P_4 + 0.1844 * P_7 ) * f_n, 1.5763 );
/* even-mode effective dielectric constant */
er_eff_e = GetParameter( TCP::EPSILONR ) - ( GetParameter( TCP::EPSILONR ) - er_eff ) / ( 1.0 + F_e );
prop_delay_e = UnitPropagationDelay( er_eff_e );
er_eff = er_eff_o_0;
P_8 = 0.7168 * ( 1.0 + 1.076 / ( 1.0 + 0.0576 * ( GetParameter( TCP::EPSILONR ) - 1.0 ) ) );
P_9 = P_8
- 0.7913 * ( 1.0 - exp( -pow( f_n / 20.0, 1.424 ) ) )
* atan( 2.481 * pow( GetParameter( TCP::EPSILONR ) / 8.0, 0.946 ) );
P_10 = 0.242 * pow( GetParameter( TCP::EPSILONR ) - 1.0, 0.55 );
P_11 = 0.6366 * ( exp( -0.3401 * f_n ) - 1.0 ) * atan( 1.263 * pow( u / 3.0, 1.629 ) );
P_12 = P_9 + ( 1.0 - P_9 ) / ( 1.0 + 1.183 * pow( u, 1.376 ) );
P_13 = 1.695 * P_10 / ( 0.414 + 1.605 * P_10 );
P_14 = 0.8928 + 0.1072 * ( 1.0 - exp( -0.42 * pow( f_n / 20.0, 3.215 ) ) );
P_15 = fabs( 1.0 - 0.8928 * ( 1.0 + P_11 ) * P_12 * exp( -P_13 * pow( g, 1.092 ) ) / P_14 );
F_o = P_1 * P_2 * pow( ( P_3 * P_4 + 0.1844 ) * f_n * P_15, 1.5763 );
/* odd-mode effective dielectric constant */
er_eff_o = GetParameter( TCP::EPSILONR ) - ( GetParameter( TCP::EPSILONR ) - er_eff ) / ( 1.0 + F_o );
prop_delay_o = UnitPropagationDelay( er_eff_o );
}
void COUPLED_MICROSTRIP::conductor_losses()
{
double e_r_eff_e_0, e_r_eff_o_0, Z0_h_e, Z0_h_o, delta;
double K, R_s, Q_c_e, Q_c_o, alpha_c_e, alpha_c_o;
e_r_eff_e_0 = er_eff_e_0;
e_r_eff_o_0 = er_eff_o_0;
Z0_h_e = Z0_e_0 * sqrt( e_r_eff_e_0 ); /* homogeneous stripline impedance */
Z0_h_o = Z0_o_0 * sqrt( e_r_eff_o_0 ); /* homogeneous stripline impedance */
delta = GetParameter( TCP::SKIN_DEPTH );
if( GetParameter( TCP::FREQUENCY ) > 0.0 )
{
/* current distribution factor (same for the two modes) */
K = exp( -1.2 * pow( ( Z0_h_e + Z0_h_o ) / ( 2.0 * TC::ZF0 ), 0.7 ) );
/* skin resistance */
R_s = 1.0 / ( GetParameter( TCP::SIGMA ) * delta );
/* correction for surface roughness */
R_s *= 1.0 + ( ( 2.0 / M_PI ) * atan( 1.40 * pow( ( GetParameter( TCP::ROUGH ) / delta ), 2.0 ) ) );
/* even-mode strip inductive quality factor */
Q_c_e = ( M_PI * Z0_h_e * GetParameter( TCP::PHYS_WIDTH ) * GetParameter( TCP::FREQUENCY ) )
/ ( R_s * TC::C0 * K );
/* even-mode losses per unit length */
alpha_c_e = ( 20.0 * M_PI / log( 10.0 ) ) * GetParameter( TCP::FREQUENCY ) * sqrt( e_r_eff_e_0 )
/ ( TC::C0 * Q_c_e );
/* odd-mode strip inductive quality factor */
Q_c_o = ( M_PI * Z0_h_o * GetParameter( TCP::PHYS_WIDTH ) * GetParameter( TCP::FREQUENCY ) )
/ ( R_s * TC::C0 * K );
/* odd-mode losses per unit length */
alpha_c_o = ( 20.0 * M_PI / log( 10.0 ) ) * GetParameter( TCP::FREQUENCY ) * sqrt( e_r_eff_o_0 )
/ ( TC::C0 * Q_c_o );
}
else
{
alpha_c_e = alpha_c_o = 0.0;
}
atten_cond_e = alpha_c_e * GetParameter( TCP::PHYS_LEN );
atten_cond_o = alpha_c_o * GetParameter( TCP::PHYS_LEN );
}
void COUPLED_MICROSTRIP::dielectric_losses()
{
double e_r, e_r_eff_e_0, e_r_eff_o_0;
double alpha_d_e, alpha_d_o;
e_r = GetParameter( TCP::EPSILONR );
e_r_eff_e_0 = er_eff_e_0;
e_r_eff_o_0 = er_eff_o_0;
alpha_d_e = ( 20.0 * M_PI / log( 10.0 ) ) * ( GetParameter( TCP::FREQUENCY ) / TC::C0 )
* ( e_r / sqrt( e_r_eff_e_0 ) ) * ( ( e_r_eff_e_0 - 1.0 ) / ( e_r - 1.0 ) ) * GetParameter( TCP::TAND );
alpha_d_o = ( 20.0 * M_PI / log( 10.0 ) ) * ( GetParameter( TCP::FREQUENCY ) / TC::C0 )
* ( e_r / sqrt( e_r_eff_o_0 ) ) * ( ( e_r_eff_o_0 - 1.0 ) / ( e_r - 1.0 ) ) * GetParameter( TCP::TAND );
atten_dielectric_e = alpha_d_e * GetParameter( TCP::PHYS_LEN );
atten_dielectric_o = alpha_d_o * GetParameter( TCP::PHYS_LEN );
}
void COUPLED_MICROSTRIP::attenuation()
{
SetParameter( TCP::SKIN_DEPTH, SkinDepth() );
conductor_losses();
dielectric_losses();
}
void COUPLED_MICROSTRIP::line_angle()
{
double e_r_eff_e, e_r_eff_o;
double v_e, v_o, lambda_g_e, lambda_g_o;
e_r_eff_e = er_eff_e;
e_r_eff_o = er_eff_o;
/* even-mode velocity */
v_e = TC::C0 / sqrt( e_r_eff_e );
/* odd-mode velocity */
v_o = TC::C0 / sqrt( e_r_eff_o );
/* even-mode wavelength */
lambda_g_e = v_e / GetParameter( TCP::FREQUENCY );
/* odd-mode wavelength */
lambda_g_o = v_o / GetParameter( TCP::FREQUENCY );
/* electrical angles */
ang_l_e = 2.0 * M_PI * GetParameter( TCP::PHYS_LEN ) / lambda_g_e; /* in radians */
ang_l_o = 2.0 * M_PI * GetParameter( TCP::PHYS_LEN ) / lambda_g_o; /* in radians */
}
void COUPLED_MICROSTRIP::diff_impedance()
{
// Note that differential impedance is exactly twice the odd mode impedance.
// Odd mode is not the same as single-ended impedance, so avoid approximations found
// on websites that use static single ended impedance as the starting point
Zdiff = 2 * Z0_o_0;
}
/*
* Z0_dispersion() - calculate frequency dependency of characteristic
* impedances
*/
void COUPLED_MICROSTRIP::Z0_dispersion()
{
double Q_0;
double Q_11, Q_12, Q_13, Q_14, Q_15, Q_16, Q_17, Q_18, Q_19, Q_20, Q_21;
double Q_22, Q_23, Q_24, Q_25, Q_26, Q_27, Q_28, Q_29;
double r_e, q_e, p_e, d_e, C_e;
double e_r_eff_o_f, e_r_eff_o_0;
double e_r_eff_single_f, e_r_eff_single_0, Z0_single_f;
double f_n, g, u, e_r;
double R_1, R_2, R_7, R_10, R_11, R_12, R_15, R_16, tmpf;
e_r = GetParameter( TCP::EPSILONR );
u = GetParameter( TCP::PHYS_WIDTH ) / GetParameter( TCP::H ); /* normalize line width */
g = GetParameter( TCP::PHYS_S ) / GetParameter( TCP::H ); /* normalize line spacing */
/* normalized frequency [GHz * mm] */
f_n = GetParameter( TCP::FREQUENCY ) * GetParameter( TCP::H ) / 1e06;
e_r_eff_single_f = m_aux_microstrip.GetParameter( TCP::EPSILON_EFF );
e_r_eff_single_0 = m_aux_microstrip.er_eff_0;
Z0_single_f = m_aux_microstrip.GetParameter( TCP::Z0 );
e_r_eff_o_f = er_eff_o;
e_r_eff_o_0 = er_eff_o_0;
Q_11 = 0.893 * ( 1.0 - 0.3 / ( 1.0 + 0.7 * ( e_r - 1.0 ) ) );
Q_12 = 2.121 * ( pow( f_n / 20.0, 4.91 ) / ( 1.0 + Q_11 * pow( f_n / 20.0, 4.91 ) ) ) * exp( -2.87 * g )
* pow( g, 0.902 );
Q_13 = 1.0 + 0.038 * pow( e_r / 8.0, 5.1 );
Q_14 = 1.0 + 1.203 * pow( e_r / 15.0, 4.0 ) / ( 1.0 + pow( e_r / 15.0, 4.0 ) );
Q_15 = 1.887 * exp( -1.5 * pow( g, 0.84 ) ) * pow( g, Q_14 )
/ ( 1.0 + 0.41 * pow( f_n / 15.0, 3.0 ) * pow( u, 2.0 / Q_13 ) / ( 0.125 + pow( u, 1.626 / Q_13 ) ) );
Q_16 = ( 1.0 + 9.0 / ( 1.0 + 0.403 * pow( e_r - 1.0, 2 ) ) ) * Q_15;
Q_17 = 0.394 * ( 1.0 - exp( -1.47 * pow( u / 7.0, 0.672 ) ) ) * ( 1.0 - exp( -4.25 * pow( f_n / 20.0, 1.87 ) ) );
Q_18 = 0.61 * ( 1.0 - exp( -2.13 * pow( u / 8.0, 1.593 ) ) ) / ( 1.0 + 6.544 * pow( g, 4.17 ) );
Q_19 = 0.21 * g * g * g * g
/ ( ( 1.0 + 0.18 * pow( g, 4.9 ) ) * ( 1.0 + 0.1 * u * u ) * ( 1.0 + pow( f_n / 24.0, 3.0 ) ) );
Q_20 = ( 0.09 + 1.0 / ( 1.0 + 0.1 * pow( e_r - 1, 2.7 ) ) ) * Q_19;
Q_21 = fabs( 1.0 - 42.54 * pow( g, 0.133 ) * exp( -0.812 * g ) * pow( u, 2.5 ) / ( 1.0 + 0.033 * pow( u, 2.5 ) ) );
r_e = pow( f_n / 28.843, 12 );
q_e = 0.016 + pow( 0.0514 * e_r * Q_21, 4.524 );
p_e = 4.766 * exp( -3.228 * pow( u, 0.641 ) );
d_e = 5.086 * q_e * ( r_e / ( 0.3838 + 0.386 * q_e ) ) * ( exp( -22.2 * pow( u, 1.92 ) ) / ( 1.0 + 1.2992 * r_e ) )
* ( pow( e_r - 1.0, 6.0 ) / ( 1.0 + 10 * pow( e_r - 1.0, 6.0 ) ) );
C_e = 1.0 + 1.275 * ( 1.0 - exp( -0.004625 * p_e * pow( e_r, 1.674 ) * pow( f_n / 18.365, 2.745 ) ) ) - Q_12 + Q_16
- Q_17 + Q_18 + Q_20;
R_1 = 0.03891 * pow( e_r, 1.4 );
R_2 = 0.267 * pow( u, 7.0 );
R_7 = 1.206 - 0.3144 * exp( -R_1 ) * ( 1.0 - exp( -R_2 ) );
R_10 = 0.00044 * pow( e_r, 2.136 ) + 0.0184;
tmpf = pow( f_n / 19.47, 6.0 );
R_11 = tmpf / ( 1.0 + 0.0962 * tmpf );
R_12 = 1.0 / ( 1.0 + 0.00245 * u * u );
R_15 = 0.707 * R_10 * pow( f_n / 12.3, 1.097 );
R_16 = 1.0 + 0.0503 * e_r * e_r * R_11 * ( 1.0 - exp( -pow( u / 15.0, 6.0 ) ) );
Q_0 = R_7 * ( 1.0 - 1.1241 * ( R_12 / R_16 ) * exp( -0.026 * pow( f_n, 1.15656 ) - R_15 ) );
/* even-mode frequency-dependent characteristic impedances */
SetParameter( TCP::Z0_E, Z0_e_0 * pow( 0.9408 * pow( e_r_eff_single_f, C_e ) - 0.9603, Q_0 )
/ pow( ( 0.9408 - d_e ) * pow( e_r_eff_single_0, C_e ) - 0.9603, Q_0 ) );
Q_29 = 15.16 / ( 1.0 + 0.196 * pow( e_r - 1.0, 2.0 ) );
tmpf = pow( e_r - 1.0, 3.0 );
Q_28 = 0.149 * tmpf / ( 94.5 + 0.038 * tmpf );
tmpf = pow( e_r - 1.0, 1.5 );
Q_27 = 0.4 * pow( g, 0.84 ) * ( 1.0 + 2.5 * tmpf / ( 5.0 + tmpf ) );
tmpf = pow( ( e_r - 1.0 ) / 13.0, 12.0 );
Q_26 = 30.0 - 22.2 * ( tmpf / ( 1.0 + 3.0 * tmpf ) ) - Q_29;
tmpf = ( e_r - 1.0 ) * ( e_r - 1.0 );
Q_25 = ( 0.3 * f_n * f_n / ( 10.0 + f_n * f_n ) ) * ( 1.0 + 2.333 * tmpf / ( 5.0 + tmpf ) );
Q_24 = 2.506 * Q_28 * pow( u, 0.894 ) * pow( ( 1.0 + 1.3 * u ) * f_n / 99.25, 4.29 ) / ( 3.575 + pow( u, 0.894 ) );
Q_23 = 1.0 + 0.005 * f_n * Q_27 / ( ( 1.0 + 0.812 * pow( f_n / 15.0, 1.9 ) ) * ( 1.0 + 0.025 * u * u ) );
Q_22 = 0.925 * pow( f_n / Q_26, 1.536 ) / ( 1.0 + 0.3 * pow( f_n / 30.0, 1.536 ) );
/* odd-mode frequency-dependent characteristic impedances */
SetParameter( TCP::Z0_O, Z0_single_f
+ ( Z0_o_0 * pow( e_r_eff_o_f / e_r_eff_o_0, Q_22 ) - Z0_single_f * Q_23 )
/ ( 1.0 + Q_24 + pow( 0.46 * g, 2.2 ) * Q_25 ) );
}
void COUPLED_MICROSTRIP::syn_err_fun( double* f1, double* f2, double s_h, double w_h, double e_r, double w_h_se,
double w_h_so )
{
double g, he;
g = cosh( 0.5 * M_PI * s_h );
he = cosh( M_PI * w_h + 0.5 * M_PI * s_h );
*f1 = ( 2.0 / M_PI ) * acosh( ( 2.0 * he - g + 1.0 ) / ( g + 1.0 ) );
*f2 = ( 2.0 / M_PI ) * acosh( ( 2.0 * he - g - 1.0 ) / ( g - 1.0 ) );
if( e_r <= 6.0 )
*f2 += ( 4.0 / ( M_PI * ( 1.0 + e_r / 2.0 ) ) ) * acosh( 1.0 + 2.0 * w_h / s_h );
else
*f2 += ( 1.0 / M_PI ) * acosh( 1.0 + 2.0 * w_h / s_h );
*f1 -= w_h_se;
*f2 -= w_h_so;
}
void COUPLED_MICROSTRIP::synth_width()
{
double Z0, e_r;
double w_h_se, w_h_so, w_h, a, ce, co, s_h;
double f1, f2, ft1, ft2, j11, j12, j21, j22, d_s_h, d_w_h, err;
double eps = 1e-04;
f1 = f2 = 0;
e_r = GetParameter( TCP::EPSILONR );
Z0 = GetParameter( TCP::Z0_E ) / 2.0;
/* Wheeler formula for single microstrip synthesis */
a = exp( Z0 * sqrt( e_r + 1.0 ) / 42.4 ) - 1.0;
w_h_se = 8.0 * sqrt( a * ( ( 7.0 + 4.0 / e_r ) / 11.0 ) + ( ( 1.0 + 1.0 / e_r ) / 0.81 ) ) / a;
Z0 = GetParameter( TCP::Z0_O ) / 2.0;
/* Wheeler formula for single microstrip synthesis */
a = exp( Z0 * sqrt( e_r + 1.0 ) / 42.4 ) - 1.0;
w_h_so = 8.0 * sqrt( a * ( ( 7.0 + 4.0 / e_r ) / 11.0 ) + ( ( 1.0 + 1.0 / e_r ) / 0.81 ) ) / a;
ce = cosh( 0.5 * M_PI * w_h_se );
co = cosh( 0.5 * M_PI * w_h_so );
/* first guess at m_parameters[PHYS_S )/h */
s_h = ( 2.0 / M_PI ) * acosh( ( ce + co - 2.0 ) / ( co - ce ) );
/* first guess at w/h */
w_h = acosh( ( ce * co - 1.0 ) / ( co - ce ) ) / M_PI - s_h / 2.0;
SetParameter( TCP::PHYS_S, s_h * GetParameter( TCP::H ) );
SetParameter( TCP::PHYS_WIDTH, w_h * GetParameter( TCP::H ) );
syn_err_fun( &f1, &f2, s_h, w_h, e_r, w_h_se, w_h_so );
/* rather crude Newton-Rhapson; we need this because the estimate of */
/* w_h is often quite far from the true value (see Akhtarzad S. et al.) */
do
{
/* compute Jacobian */
syn_err_fun( &ft1, &ft2, s_h + eps, w_h, e_r, w_h_se, w_h_so );
j11 = ( ft1 - f1 ) / eps;
j21 = ( ft2 - f2 ) / eps;
syn_err_fun( &ft1, &ft2, s_h, w_h + eps, e_r, w_h_se, w_h_so );
j12 = ( ft1 - f1 ) / eps;
j22 = ( ft2 - f2 ) / eps;
/* compute next step */
d_s_h = ( -f1 * j22 + f2 * j12 ) / ( j11 * j22 - j21 * j12 );
d_w_h = ( -f2 * j11 + f1 * j21 ) / ( j11 * j22 - j21 * j12 );
//g_print("j11 = %e\tj12 = %e\tj21 = %e\tj22 = %e\n", j11, j12, j21, j22);
//g_print("det = %e\n", j11*j22 - j21*j22);
//g_print("d_s_h = %e\td_w_h = %e\n", d_s_h, d_w_h);
s_h += d_s_h;
w_h += d_w_h;
/* check the error */
syn_err_fun( &f1, &f2, s_h, w_h, e_r, w_h_se, w_h_so );
err = sqrt( f1 * f1 + f2 * f2 );
/* converged ? */
} while( err > 1e-04 );
SetParameter( TCP::PHYS_S, s_h * GetParameter( TCP::H ) );
SetParameter( TCP::PHYS_WIDTH, w_h * GetParameter( TCP::H ) );
}
void COUPLED_MICROSTRIP::syn_fun( double* f1, double* f2, double s_h, double w_h, double Z0_e, double Z0_o )
{
SetParameter( TCP::PHYS_S, s_h * GetParameter( TCP::H ) );
SetParameter( TCP::PHYS_WIDTH, w_h * GetParameter( TCP::H ) );
/* compute coupled microstrip parameters */
Analyse();
*f1 = GetParameter( TCP::Z0_E ) - Z0_e;
*f2 = GetParameter( TCP::Z0_O ) - Z0_o;
}

View File

@ -0,0 +1,202 @@
/*
* Copyright (C) 2001 Gopal Narayanan <gopal@astro.umass.edu>
* Copyright (C) 2002 Claudio Girardi <claudio.girardi@ieee.org>
* Copyright (C) 2005, 2006 Stefan Jahn <stefan@lkcc.org>
* Modified for Kicad: 2018 Jean-Pierre Charras <jp.charras at wanadoo.fr>
* Copyright The KiCad Developers, see AUTHORS.txt for contributors.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this package; see the file COPYING. If not, write to
* the Free Software Foundation, Inc., 51 Franklin Street - Fifth Floor,
* Boston, MA 02110-1301, USA.
*/
#ifndef TRANSLINE_CALCULATIONS_COUPLED_MICROSTRIP_H
#define TRANSLINE_CALCULATIONS_COUPLED_MICROSTRIP_H
#include <transline_calculations/transline_calculation_base.h>
#include <transline_calculations/microstrip.h>
class COUPLED_MICROSTRIP : public TRANSLINE_CALCULATION_BASE
{
using TCP = TRANSLINE_PARAMETERS;
public:
COUPLED_MICROSTRIP() :
TRANSLINE_CALCULATION_BASE( { TCP::Z0_E,
TCP::Z0_O,
TCP::Z_DIFF,
TCP::ANG_L,
TCP::PHYS_WIDTH,
TCP::PHYS_LEN,
TCP::PHYS_S,
TCP::H,
TCP::T,
TCP::H_T,
TCP::FREQUENCY,
TCP::EPSILONR,
TCP::EPSILON_EFF_EVEN,
TCP::EPSILON_EFF_ODD,
TCP::UNIT_PROP_DELAY_EVEN,
TCP::UNIT_PROP_DELAY_ODD,
TCP::ATTEN_COND_EVEN,
TCP::ATTEN_COND_ODD,
TCP::ATTEN_DILECTRIC_EVEN,
TCP::ATTEN_DILECTRIC_ODD,
TCP::SKIN_DEPTH,
TCP::MURC,
TCP::SIGMA,
TCP::ROUGH,
TCP::TAND } )
{
}
/// Analyse track geometry parameters to output Z0 and Ang_L
void Analyse() override;
/// Synthesis track geometry parameters to match given Z0
bool Synthesize( SYNTHESIZE_OPTS aOpts ) override;
private:
/// Sets the output values and status following analysis
void SetAnalysisResults() override;
/// Sets the output values and status following synthesis
void SetSynthesisResults() override;
/**
* Computes the thickness effect on normalized width for a single microstrip line
*
* References: H. A. Atwater, "Simplified Design Equations for Microstrip Line Parameters", Microwave Journal,
* pp. 109-115,November 1989.
*/
double delta_u_thickness_single( double, double );
/**
* Compute the thickness effect on normalized width for coupled microstrips
*
* References: Rolf Jansen, "High-Speed Computation of Single and Coupled Microstrip Parameters Including
* Dispersion, High-Order Modes, Loss and Finite Strip Thickness", IEEE Trans. MTT, vol. 26, no. 2, pp. 75-82,
* Feb. 1978
*/
void delta_u_thickness();
/// Computes initial parameters for a single microstrip
void compute_single_line();
/// Compute the filling factor for the coupled microstrip even mode without cover and zero conductor thickness
double filling_factor_even( double, double, double );
/**
* Compute the filling factor for the coupled microstrip odd mode without cover and zero conductor thickness
*/
double filling_factor_odd( double, double, double );
/// Compute the cover effect on filling factor for the even mode
double delta_q_cover_even( double );
/// Compute the cover effect on filling factor for the odd mode
double delta_q_cover_odd( double );
/**
* Compute the static effective dielectric constants
*
* References: Manfred Kirschning and Rolf Jansen, "Accurate Wide-Range Design Equations for the Frequency-Dependent
* Characteristic of Parallel Coupled Microstrip Lines", IEEE Trans. MTT, vol. 32, no. 1, Jan. 1984
*/
void er_eff_static();
/**
* Compute the even mode impedance correction for a homogeneous microstrip due to the cover
*
* References: S. March, "Microstrip Packaging: Watch the Last Step", Microwaves, vol. 20, no. 13, pp. 83.94,
* Dec. 1981.
*/
double delta_Z0_even_cover( double, double, double );
/**
* Compute the odd mode impedance correction for a homogeneous microstrip due to the cover
*
* References: S. March, "Microstrip Packaging: Watch the Last Step", Microwaves, vol. 20, no. 13, pp. 83.94,
* Dec. 1981.
*/
double delta_Z0_odd_cover( double, double, double );
/**
* Compute the static even- and odd-mode static impedances
*
* References: Manfred Kirschning and Rolf Jansen, "Accurate Wide-Range Design Equations for the Frequency-Dependent
* Characteristic of Parallel Coupled Microstrip Lines", IEEE Trans. MTT, vol. 32, no. 1, Jan. 1984
*/
void Z0_even_odd();
/// Compute er_eff as a function of frequency
void er_eff_freq();
/// Compute conductor losses per unit length
void conductor_losses();
/// Compute dielectric losses per unit length
void dielectric_losses();
/// Compute attenuation
void attenuation();
/// Compute electrical length in radians
void line_angle();
/// Calculate the differential impedance of the coupled microstrips
void diff_impedance();
/// Calculate frequency dependency of characteristic impedances
void Z0_dispersion();
/// Error function to minimise when synthesising trace geometry
void syn_err_fun( double*, double*, double, double, double, double, double );
/**
* Calculate widths given Z0 and e_r
*
* From Akhtarzad S. et al., "The design of coupled microstrip lines", IEEE Trans. MTT-23, June 1975 and
* Hinton, J.H., "On design of coupled microstrip lines", IEEE Trans. MTT-28, March 1980
*/
void synth_width();
void syn_fun( double*, double*, double, double, double, double );
/// Runs intermediate single-track calculations
MICROSTRIP m_aux_microstrip;
double w_t_e{ 0.0 };
double w_t_o{ 0.0 };
double er_eff_e_0{ 0.0 };
double er_eff_o_0{ 0.0 };
double Z0_e_0{ 0.0 };
double Z0_o_0{ 0.0 };
double er_eff_e{ 0.0 };
double er_eff_o{ 0.0 };
double prop_delay_e{ 0.0 };
double prop_delay_o{ 0.0 };
double atten_cond_e{ 0.0 };
double atten_cond_o{ 0.0 };
double atten_dielectric_e{ 0.0 };
double atten_dielectric_o{ 0.0 };
double ang_l_e{ 0.0 };
double ang_l_o{ 0.0 };
double Zdiff{ 0.0 };
};
#endif //TRANSLINE_CALCULATIONS_COUPLED_MICROSTRIP_H

View File

@ -0,0 +1,393 @@
/*
* Copyright The KiCad Developers, see AUTHORS.txt for contributors.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this package; see the file COPYING. If not, write to
* the Free Software Foundation, Inc., 51 Franklin Street - Fifth Floor,
* Boston, MA 02110-1301, USA.
*/
/*
* This implements the calculations described in:
*
* [1] S. B. Cohn, "Characteristic Impedance of the Shielded-Strip Transmission Line," in Transactions of the IRE
* Professional Group on Microwave Theory and Techniques, vol. 2, no. 2, pp. 52-57, July 1954
* [2] S. B. Cohn, "Shielded Coupled-Strip Transmission Line," in IRE Transactions on Microwave Theory and Techniques,
* vol. 3, no. 5, pp. 29-38, October 1955
*/
#include <transline_calculations/coupled_stripline.h>
#include <transline_calculations/units.h>
#include <transline_calculations/units_scales.h>
namespace TC = TRANSLINE_CALCULATIONS;
using TCP = TRANSLINE_PARAMETERS;
void COUPLED_STRIPLINE::Analyse()
{
// Calculate skin depth
SetParameter( TCP::SKIN_DEPTH, SkinDepth() );
// Get analysis parameters
double w = GetParameter( TCP::PHYS_WIDTH );
double t = GetParameter( TCP::T );
double s = GetParameter( TCP::PHYS_S );
double h = GetParameter( TCP::H );
const double er = GetParameter( TCP::EPSILONR );
calcZeroThicknessCoupledImpedances( h, w, s, er );
// We've got the impedances now for an infinitely thin line
if( t == 0.0 )
{
SetParameter( TCP::Z0_E, Z0_e_w_h_0_s_h );
SetParameter( TCP::Z0_O, Z0_o_w_h_0_s_h );
}
else
{
calcSingleStripImpedances();
calcFringeCapacitances( h, t, er );
calcZ0EvenMode();
calcZ0OddMode( t, s );
}
calcLosses();
calcDielectrics();
}
bool COUPLED_STRIPLINE::Synthesize( const SYNTHESIZE_OPTS aOpts )
{
if( aOpts == SYNTHESIZE_OPTS::FIX_WIDTH )
return MinimiseZ0Error1D( TCP::PHYS_S, TCP::Z0_O );
if( aOpts == SYNTHESIZE_OPTS::FIX_SPACING )
return MinimiseZ0Error1D( TCP::PHYS_WIDTH, TCP::Z0_O );
// This synthesis approach is modified from wcalc, which is released under GPL version 2
// Copyright (C) 1999, 2000, 2001, 2002, 2003, 2004, 2006 Dan McMahill
// All rights reserved
double ze0 = 0;
double zo0 = 0;
const double h = GetParameter( TCP::H );
const double er = GetParameter( TCP::EPSILONR );
const double z0e_target = GetParameter( TCP::Z0_E );
const double z0o_target = GetParameter( TCP::Z0_O );
// Calculate Z0 and coupling, k
const double z0 = sqrt( z0e_target * z0o_target );
const double k = ( z0e_target - z0o_target ) / ( z0e_target + z0o_target );
int maxiters = 50;
// Initial guess at a solution. Note that this is an initial guess for coupled microstrip, not coupled stripline...
static constexpr double ai[] = { 1, -0.301, 3.209, -27.282, 56.609, -37.746 };
static constexpr double bi[] = { 0.020, -0.623, 17.192, -68.946, 104.740, -16.148 };
static constexpr double ci[] = { 0.002, -0.347, 7.171, -36.910, 76.132, -51.616 };
const double AW = exp( z0 * sqrt( er + 1.0 ) / 42.4 ) - 1.0;
const double F1 = 8.0 * sqrt( AW * ( 7.0 + 4.0 / er ) / 11.0 + ( 1.0 + 1.0 / er ) / 0.81 ) / AW;
double F2 = 0.0, F3 = 0.0;
;
for( int i = 0; i <= 5; i++ )
F2 = F2 + ai[i] * pow( k, i );
for( int i = 0; i <= 5; i++ )
F3 = F3 + ( bi[i] - ci[i] * ( 9.6 - er ) ) * pow( ( 0.6 - k ), static_cast<double>( i ) );
double w = h * fabs( F1 * F2 );
double s = h * fabs( F1 * F3 );
int iters = 0;
bool done = false;
double delta = 0.0;
delta = TC::UNIT_MIL * 1e-5;
const double cval = 1e-12 * z0e_target * z0o_target;
while( !done && iters < maxiters )
{
iters++;
// Compute impedances with initial solution guess
SetParameter( TCP::PHYS_WIDTH, w );
SetParameter( TCP::PHYS_S, s );
Analyse();
// Check for convergence
ze0 = GetParameter( TCP::Z0_E );
zo0 = GetParameter( TCP::Z0_O );
const double err = pow( ( ze0 - z0e_target ), 2.0 ) + pow( ( zo0 - z0o_target ), 2.0 );
if( err < cval )
{
done = true;
}
else
{
// Approximate the first Jacobian
SetParameter( TCP::PHYS_WIDTH, w + delta );
SetParameter( TCP::PHYS_S, s );
Analyse();
const double ze1 = GetParameter( TCP::Z0_E );
const double zo1 = GetParameter( TCP::Z0_O );
SetParameter( TCP::PHYS_WIDTH, w );
SetParameter( TCP::PHYS_S, s + delta );
Analyse();
const double ze2 = GetParameter( TCP::Z0_E );
const double zo2 = GetParameter( TCP::Z0_O );
const double dedw = ( ze1 - ze0 ) / delta;
const double dodw = ( zo1 - zo0 ) / delta;
const double deds = ( ze2 - ze0 ) / delta;
const double dods = ( zo2 - zo0 ) / delta;
// Find the determinate
const double d = dedw * dods - deds * dodw;
// Estimate the new solution, but don't change by more than 10% at a time to avoid convergence problems
double dw = -1.0 * ( ( ze0 - z0e_target ) * dods - ( zo0 - z0o_target ) * deds ) / d;
if( fabs( dw ) > 0.1 * w )
{
if( dw > 0.0 )
dw = 0.1 * w;
else
dw = -0.1 * w;
}
w = fabs( w + dw );
double ds = ( ( ze0 - z0e_target ) * dodw - ( zo0 - z0o_target ) * dedw ) / d;
if( fabs( ds ) > 0.1 * s )
{
if( ds > 0.0 )
ds = 0.1 * s;
else
ds = -0.1 * s;
}
s = fabs( s + ds );
}
}
if( !done )
return false;
// Recompute with the final parameters
SetParameter( TCP::PHYS_WIDTH, w );
SetParameter( TCP::PHYS_S, s );
Analyse();
// Reset the impedances
SetParameter( TCP::Z0_E, z0e_target );
SetParameter( TCP::Z0_O, z0o_target );
return true;
}
void COUPLED_STRIPLINE::SetAnalysisResults()
{
SetAnalysisResult( TCP::EPSILON_EFF_EVEN, e_eff_e );
SetAnalysisResult( TCP::EPSILON_EFF_ODD, e_eff_o );
SetAnalysisResult( TCP::UNIT_PROP_DELAY_EVEN, unit_prop_delay_e );
SetAnalysisResult( TCP::UNIT_PROP_DELAY_ODD, unit_prop_delay_o );
SetAnalysisResult( TCP::SKIN_DEPTH, GetParameter( TCP::SKIN_DEPTH ) );
const double Z0_E = GetParameter( TCP::Z0_E );
const double Z0_O = GetParameter( TCP::Z0_O );
const double Z_DIFF = GetParameter( TCP::Z_DIFF );
const double W = GetParameter( TCP::PHYS_WIDTH );
const double L = GetParameter( TCP::PHYS_LEN );
const double S = GetParameter( TCP::PHYS_S );
const bool Z0_E_invalid = !std::isfinite( Z0_E ) || Z0_E <= 0;
const bool Z0_O_invalid = !std::isfinite( Z0_O ) || Z0_O <= 0;
const bool Z_DIFF_invalid = !std::isfinite( Z_DIFF ) || Z_DIFF <= 0;
const bool ANG_L_invalid = !std::isfinite( ang_l ) || ang_l < 0;
const bool W_invalid = !std::isfinite( W ) || W <= 0;
const bool L_invalid = !std::isfinite( L ) || L < 0;
const bool S_invalid = !std::isfinite( S ) || S <= 0;
SetAnalysisResult( TCP::Z0_E, Z0_E, Z0_E_invalid ? TRANSLINE_STATUS::ERROR : TRANSLINE_STATUS::OK );
SetAnalysisResult( TCP::Z0_O, Z0_O, Z0_O_invalid ? TRANSLINE_STATUS::ERROR : TRANSLINE_STATUS::OK );
SetAnalysisResult( TCP::Z_DIFF, Z_DIFF, Z_DIFF_invalid ? TRANSLINE_STATUS::ERROR : TRANSLINE_STATUS::OK );
SetAnalysisResult( TCP::ANG_L, ang_l, ANG_L_invalid ? TRANSLINE_STATUS::ERROR : TRANSLINE_STATUS::OK );
SetAnalysisResult( TCP::PHYS_WIDTH, W, W_invalid ? TRANSLINE_STATUS::WARNING : TRANSLINE_STATUS::OK );
SetAnalysisResult( TCP::PHYS_LEN, L, L_invalid ? TRANSLINE_STATUS::WARNING : TRANSLINE_STATUS::OK );
SetAnalysisResult( TCP::PHYS_S, S, S_invalid ? TRANSLINE_STATUS::WARNING : TRANSLINE_STATUS::OK );
}
void COUPLED_STRIPLINE::SetSynthesisResults()
{
SetSynthesisResult( TCP::EPSILON_EFF_EVEN, e_eff_e );
SetSynthesisResult( TCP::EPSILON_EFF_ODD, e_eff_o );
SetSynthesisResult( TCP::UNIT_PROP_DELAY_EVEN, unit_prop_delay_e );
SetSynthesisResult( TCP::UNIT_PROP_DELAY_ODD, unit_prop_delay_o );
SetSynthesisResult( TCP::SKIN_DEPTH, GetParameter( TCP::SKIN_DEPTH ) );
const double Z0_E = GetParameter( TCP::Z0_E );
const double Z0_O = GetParameter( TCP::Z0_O );
const double Z_DIFF = GetParameter( TCP::Z_DIFF );
const double W = GetParameter( TCP::PHYS_WIDTH );
const double L = GetParameter( TCP::PHYS_LEN );
const double S = GetParameter( TCP::PHYS_S );
const bool Z0_E_invalid = !std::isfinite( Z0_E ) || Z0_E <= 0;
const bool Z0_O_invalid = !std::isfinite( Z0_O ) || Z0_O <= 0;
const bool Z_DIFF_invalid = !std::isfinite( Z_DIFF ) || Z_DIFF <= 0;
const bool ANG_L_invalid = !std::isfinite( ang_l ) || ang_l < 0;
const bool W_invalid = !std::isfinite( W ) || W <= 0;
const bool L_invalid = !std::isfinite( L ) || L < 0;
const bool S_invalid = !std::isfinite( S ) || S <= 0;
SetSynthesisResult( TCP::Z0_E, Z0_E, Z0_E_invalid ? TRANSLINE_STATUS::WARNING : TRANSLINE_STATUS::OK );
SetSynthesisResult( TCP::Z0_O, Z0_O, Z0_O_invalid ? TRANSLINE_STATUS::WARNING : TRANSLINE_STATUS::OK );
SetSynthesisResult( TCP::Z_DIFF, Z_DIFF, Z_DIFF_invalid ? TRANSLINE_STATUS::WARNING : TRANSLINE_STATUS::OK );
SetSynthesisResult( TCP::ANG_L, ang_l, ANG_L_invalid ? TRANSLINE_STATUS::WARNING : TRANSLINE_STATUS::OK );
SetSynthesisResult( TCP::PHYS_WIDTH, W, W_invalid ? TRANSLINE_STATUS::ERROR : TRANSLINE_STATUS::OK );
SetSynthesisResult( TCP::PHYS_LEN, L, L_invalid ? TRANSLINE_STATUS::ERROR : TRANSLINE_STATUS::OK );
SetSynthesisResult( TCP::PHYS_S, S, S_invalid ? TRANSLINE_STATUS::ERROR : TRANSLINE_STATUS::OK );
}
void COUPLED_STRIPLINE::calcFringeCapacitances( const double h, const double t, const double er )
{
// Reference [1], Eq. 2
C_f_t_h = ( TC::E0 * er / M_PI )
* ( ( 2.0 / ( 1.0 - t / h ) ) * log( ( 1.0 / ( 1.0 - t / h ) ) + 1.0 )
- ( 1.0 / ( 1.0 - t / h ) - 1.0 ) * log( ( 1.0 / pow( 1.0 - t / h, 2.0 ) ) - 1.0 ) );
// Reference [2], Eq. 13
C_f_0 = ( TC::E0 * er / M_PI ) * 2.0 * log( 2.0 );
}
void COUPLED_STRIPLINE::calcZeroThicknessCoupledImpedances( const double h, const double w, const double s,
const double er )
{
// Reference [2], Eqs. 2 - 7
const double k_e = tanh( M_PI * w / ( 2.0 * h ) ) * tanh( M_PI * ( w + s ) / ( 2.0 * h ) );
const double k_o = tanh( M_PI * w / ( 2.0 * h ) ) * coth( M_PI * ( w + s ) / ( 2.0 * h ) );
const double k_e_p = std::sqrt( 1 - std::pow( k_e, 2 ) );
const double k_o_p = std::sqrt( 1 - std::pow( k_o, 2 ) );
Z0_e_w_h_0_s_h = ( TC::ZF0 / ( 4.0 * std::sqrt( er ) ) )
* ( EllipticIntegral( k_e_p ).first / EllipticIntegral( k_e ).first );
Z0_o_w_h_0_s_h = ( TC::ZF0 / ( 4.0 * std::sqrt( er ) ) )
* ( EllipticIntegral( k_o_p ).first / EllipticIntegral( k_o ).first );
}
void COUPLED_STRIPLINE::calcSingleStripImpedances()
{
const double er = GetParameter( TCP::EPSILONR );
const double h = GetParameter( TCP::H );
const double w = GetParameter( TCP::PHYS_WIDTH );
// Finite-thickness single strip impedance
Z0_w_h_t_h = calcZ0SymmetricStripline();
// Zero-thickness single strip impedance
// Reference [1], Eqs. 5 - 6 (corrected for sqrt(e_r))
const double k = sech( M_PI * w / ( 2.0 * h ) );
const double k_p = tanh( M_PI * w / ( 2.0 * h ) );
Z0_w_h_0 =
( TC::ZF0 / ( 4.0 * std::sqrt( er ) ) ) * ( EllipticIntegral( k ).first / EllipticIntegral( k_p ).first );
}
void COUPLED_STRIPLINE::calcZ0EvenMode()
{
// Reference [2], Eq. 18
const double Z_e =
1.0 / ( ( 1.0 / Z0_w_h_t_h ) - ( C_f_t_h / C_f_0 ) * ( ( 1.0 / Z0_w_h_0 ) - ( 1.0 / Z0_e_w_h_0_s_h ) ) );
SetParameter( TCP::Z0_E, Z_e );
}
void COUPLED_STRIPLINE::calcZ0OddMode( const double t, const double s )
{
// Reference [2], Eq. 20
const double Z_o_1 =
1.0 / ( ( 1.0 / Z0_w_h_t_h ) + ( C_f_t_h / C_f_0 ) * ( ( 1.0 / Z0_o_w_h_0_s_h ) - ( 1.0 / Z0_w_h_0 ) ) );
// Reference [2], Eq. 22
const double Z_o_2 =
1.0
/ ( ( 1.0 / Z0_o_w_h_0_s_h ) + ( ( 1.0 / Z0_w_h_t_h ) - ( 1.0 / Z0_w_h_0 ) )
- ( 2.0 / TC::ZF0 ) * ( C_f_t_h / TC::E0 - C_f_0 / TC::E0 ) + ( 2.0 * t ) / ( TC::ZF0 * s ) );
const double Z_o = s / t >= 5.0 ? Z_o_1 : Z_o_2;
SetParameter( TCP::Z0_O, Z_o );
SetParameter( TCP::Z_DIFF, 2.0 * Z_o );
}
void COUPLED_STRIPLINE::calcLosses()
{
}
void COUPLED_STRIPLINE::calcDielectrics()
{
// We assume here that the dielectric is homogenous surrounding the strips - in this case, the odd or even modes
// don't change the effective dielectric constant of the transmission mode. This would not be the case if the
// dielectric were inhomogenous, as there is more electric field permeating the dielectric between the traces in
// the odd mode compared to the even mode.
const double e_r = GetParameter( TCP::EPSILONR );
e_eff_e = e_r;
e_eff_o = e_r;
// Both modes have the same propagation delay
const double unitPropDelay = UnitPropagationDelay( e_r );
unit_prop_delay_e = unitPropDelay;
unit_prop_delay_o = unitPropDelay;
// Electrical length (in radians)
const double v = TC::C0 / sqrt( e_r );
const double lambda_g = v / GetParameter( TCP::FREQUENCY );
ang_l = 2.0 * M_PI * GetParameter( TCP::PHYS_LEN ) / lambda_g;
}
double COUPLED_STRIPLINE::calcZ0SymmetricStripline()
{
m_striplineCalc.SetParameter( TRANSLINE_PARAMETERS::EPSILONR, GetParameter( TCP::EPSILONR ) );
m_striplineCalc.SetParameter( TRANSLINE_PARAMETERS::T, GetParameter( TCP::T ) );
m_striplineCalc.SetParameter( TRANSLINE_PARAMETERS::STRIPLINE_A, GetParameter( TCP::H ) / 2.0 );
m_striplineCalc.SetParameter( TRANSLINE_PARAMETERS::H, GetParameter( TCP::H ) );
m_striplineCalc.SetParameter( TRANSLINE_PARAMETERS::PHYS_LEN, GetParameter( TCP::PHYS_LEN ) );
m_striplineCalc.SetParameter( TRANSLINE_PARAMETERS::FREQUENCY, GetParameter( TCP::FREQUENCY ) );
m_striplineCalc.SetParameter( TRANSLINE_PARAMETERS::TAND, 0.0 );
m_striplineCalc.SetParameter( TRANSLINE_PARAMETERS::PHYS_WIDTH, GetParameter( TCP::PHYS_WIDTH ) );
m_striplineCalc.SetParameter( TRANSLINE_PARAMETERS::ANG_L, 0 );
m_striplineCalc.SetParameter( TRANSLINE_PARAMETERS::SIGMA, GetParameter( TCP::SIGMA ) );
m_striplineCalc.SetParameter( TRANSLINE_PARAMETERS::MURC, GetParameter( TCP::MURC ) );
m_striplineCalc.Analyse();
return m_striplineCalc.GetParameter( TCP::Z0 );
}

View File

@ -0,0 +1,104 @@
/*
* Copyright The KiCad Developers, see AUTHORS.txt for contributors.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this package; see the file COPYING. If not, write to
* the Free Software Foundation, Inc., 51 Franklin Street - Fifth Floor,
* Boston, MA 02110-1301, USA.
*/
#ifndef TRANSLINE_CALCULATIONS_COUPLED_STRIPLINE_H
#define TRANSLINE_CALCULATIONS_COUPLED_STRIPLINE_H
#include <transline_calculations/transline_calculation_base.h>
#include <transline_calculations/stripline.h>
/*
* This implements the calculations described in:
*
* [1] S. B. Cohn, "Characteristic Impedance of the Shielded-Strip Transmission Line," in Transactions of the IRE
* Professional Group on Microwave Theory and Techniques, vol. 2, no. 2, pp. 52-57, July 1954
* [2] S. B. Cohn, "Shielded Coupled-Strip Transmission Line," in IRE Transactions on Microwave Theory and Techniques,
* vol. 3, no. 5, pp. 29-38, October 1955
*/
class COUPLED_STRIPLINE : public TRANSLINE_CALCULATION_BASE
{
using TCP = TRANSLINE_PARAMETERS;
public:
COUPLED_STRIPLINE() :
TRANSLINE_CALCULATION_BASE( { TCP::SKIN_DEPTH, TCP::Z0_E, TCP::Z0_O, TCP::Z_DIFF, TCP::PHYS_WIDTH,
TCP::FREQUENCY, TCP::PHYS_LEN, TCP::H, TCP::PHYS_S, TCP::T, TCP::EPSILONR,
TCP::MURC, TCP::SIGMA, TCP::ANG_L } )
{
}
/// Analyse track geometry parameters to output Z0 and Ang_L
void Analyse() override;
/// Synthesis track geometry parameters to match given Z0
bool Synthesize( SYNTHESIZE_OPTS aOpts ) override;
private:
/// Sets the output values and status following analysis
void SetAnalysisResults() override;
/// Sets the output values and status following synthesis
void SetSynthesisResults() override;
/// Calculates the impedance of a finite-width single strip
double calcZ0SymmetricStripline();
/// Calculate the coupling fringe capacitances
void calcFringeCapacitances( double h, double t, double er );
/// Calculates impedances of finite- and zero-thickness single strips
void calcSingleStripImpedances();
/// Calculates zero-thickness coupled strip impedances
void calcZeroThicknessCoupledImpedances( double h, double w, double s, double er );
/// Calculates even mode Z0
void calcZ0EvenMode();
/// Calculates odd mode Z0
void calcZ0OddMode( double t, double s );
/// Calculates conductor and dielectric losses
void calcLosses();
/// Calculate dialectric and propagation parameters
void calcDielectrics();
double C_f_0{ 0.0 }; ///< Fringing capacitance from one edge to ground of zero thickness strip
double C_f_t_h{ 0.0 }; ///< Fringing capacitance of single strip of finite width
double Z0_w_h_0{ 0.0 }; ///< Impedance of single strip of zero thickness
double Z0_w_h_t_h{ 0.0 }; ///< Impedance of single strip of finite thickness
double Z0_e_w_h_0_s_h{ 0.0 }; ///< Even mode impedance of coupled zero thickness strips
double Z0_o_w_h_0_s_h{ 0.0 }; ///< Odd mode impedance of coupled zero thickness strips
double e_eff_e{ 0.0 }; ///< Even mode effective dielectric constant
double e_eff_o{ 0.0 }; ///< Odd mode effective dielectric constant
double ang_l{ 0.0 }; ///< Angular length (rad)
double unit_prop_delay_e{ 0.0 }; ///< Even mode unit propagation delay (ps/cm)
double unit_prop_delay_o{ 0.0 }; ///< Odd mode unit propagation delay (ps/cm)
/// Calculator used to determine single stripline values
STRIPLINE m_striplineCalc;
};
#endif //TRANSLINE_CALCULATIONS_COUPLED_STRIPLINE_H

View File

@ -0,0 +1,396 @@
/*
* Copyright (C) 2001 Gopal Narayanan <gopal@astro.umass.edu>
* Copyright (C) 2002 Claudio Girardi <claudio.girardi@ieee.org>
* Copyright (C) 2005, 2006 Stefan Jahn <stefan@lkcc.org>
* Modified for Kicad: 2018 Jean-Pierre Charras <jp.charras at wanadoo.fr>
* Copyright The KiCad Developers, see AUTHORS.txt for contributors.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this package; see the file COPYING. If not, write to
* the Free Software Foundation, Inc., 51 Franklin Street - Fifth Floor,
* Boston, MA 02110-1301, USA.
*/
#include <transline_calculations/microstrip.h>
#include <transline_calculations/units.h>
namespace TC = TRANSLINE_CALCULATIONS;
using TCP = TRANSLINE_PARAMETERS;
void MICROSTRIP::Analyse()
{
// Effective permeability
mur_eff_ms();
// Static impedance
microstrip_Z0();
// Calculate freq dependence of er and Z0
dispersion();
// Calculate electrical lengths
line_angle();
// Calculate losses
attenuation();
}
bool MICROSTRIP::Synthesize( const SYNTHESIZE_OPTS aOpts )
{
const double z0_dest = GetParameter( TCP::Z0 );
const double angl_dest = GetParameter( TCP::ANG_L );
// Calculate width and use for initial value in Newton's method
SetParameter( TCP::PHYS_WIDTH, SynthesizeWidth() );
// Optimise Z0, varying width
if( !MinimiseZ0Error1D( TCP::PHYS_WIDTH, TCP::Z0 ) )
return false;
// Re-calculate with required output parameters
SetParameter( TCP::Z0, z0_dest );
SetParameter( TCP::ANG_L, angl_dest );
double const er_eff = GetParameter( TCP::EPSILON_EFF );
SetParameter( TCP::PHYS_LEN, TC::C0 / GetParameter( TCP::FREQUENCY ) / sqrt( er_eff * mur_eff )
* GetParameter( TCP::ANG_L ) / 2.0 / M_PI ); /* in m */
Analyse();
// Set the output parameters
SetParameter( TCP::Z0, z0_dest );
SetParameter( TCP::ANG_L, angl_dest );
SetParameter( TCP::PHYS_LEN, TC::C0 / GetParameter( TCP::FREQUENCY ) / sqrt( er_eff * mur_eff )
* GetParameter( TCP::ANG_L ) / 2.0 / M_PI ); /* in m */
return true;
}
void MICROSTRIP::SetAnalysisResults()
{
SetAnalysisResult( TCP::EPSILON_EFF, GetParameter( TCP::EPSILON_EFF ) );
SetAnalysisResult( TCP::UNIT_PROP_DELAY, GetParameter( TCP::UNIT_PROP_DELAY ) );
SetAnalysisResult( TCP::ATTEN_COND, GetParameter( TCP::ATTEN_COND ) );
SetAnalysisResult( TCP::ATTEN_DILECTRIC, GetParameter( TCP::ATTEN_DILECTRIC ) );
SetAnalysisResult( TCP::SKIN_DEPTH, GetParameter( TCP::SKIN_DEPTH ) );
const double Z0 = GetParameter( TCP::Z0 );
const double ANG_L = GetParameter( TCP::ANG_L );
const double L = GetParameter( TCP::PHYS_LEN );
const double W = GetParameter( TCP::PHYS_WIDTH );
const bool Z0_invalid = !std::isfinite( Z0 ) || Z0 < 0;
const bool ANG_L_invalid = !std::isfinite( ANG_L ) || ANG_L < 0;
const bool L_invalid = !std::isfinite( L ) || L < 0;
const bool W_invalid = !std::isfinite( W ) || W <= 0;
SetAnalysisResult( TCP::Z0, Z0, Z0_invalid ? TRANSLINE_STATUS::ERROR : TRANSLINE_STATUS::OK );
SetAnalysisResult( TCP::ANG_L, ANG_L, ANG_L_invalid ? TRANSLINE_STATUS::ERROR : TRANSLINE_STATUS::OK );
SetAnalysisResult( TCP::PHYS_LEN, L, L_invalid ? TRANSLINE_STATUS::WARNING : TRANSLINE_STATUS::OK );
SetAnalysisResult( TCP::PHYS_WIDTH, W, W_invalid ? TRANSLINE_STATUS::WARNING : TRANSLINE_STATUS::OK );
}
void MICROSTRIP::SetSynthesisResults()
{
SetSynthesisResult( TCP::EPSILON_EFF, GetParameter( TCP::EPSILON_EFF ) );
SetSynthesisResult( TCP::UNIT_PROP_DELAY, GetParameter( TCP::UNIT_PROP_DELAY ) );
SetSynthesisResult( TCP::ATTEN_COND, GetParameter( TCP::ATTEN_COND ) );
SetSynthesisResult( TCP::ATTEN_DILECTRIC, GetParameter( TCP::ATTEN_DILECTRIC ) );
SetSynthesisResult( TCP::SKIN_DEPTH, GetParameter( TCP::SKIN_DEPTH ) );
const double Z0 = GetParameter( TCP::Z0 );
const double ANG_L = GetParameter( TCP::ANG_L );
const double L = GetParameter( TCP::PHYS_LEN );
const double W = GetParameter( TCP::PHYS_WIDTH );
const bool Z0_invalid = !std::isfinite( Z0 ) || Z0 < 0;
const bool ANG_L_invalid = !std::isfinite( ANG_L ) || ANG_L < 0;
const bool L_invalid = !std::isfinite( L ) || L < 0;
const bool W_invalid = !std::isfinite( W ) || W <= 0;
SetSynthesisResult( TCP::Z0, Z0, Z0_invalid ? TRANSLINE_STATUS::WARNING : TRANSLINE_STATUS::OK );
SetSynthesisResult( TCP::ANG_L, ANG_L, ANG_L_invalid ? TRANSLINE_STATUS::WARNING : TRANSLINE_STATUS::OK );
SetSynthesisResult( TCP::PHYS_LEN, L, L_invalid ? TRANSLINE_STATUS::ERROR : TRANSLINE_STATUS::OK );
SetSynthesisResult( TCP::PHYS_WIDTH, W, W_invalid ? TRANSLINE_STATUS::ERROR : TRANSLINE_STATUS::OK );
}
double MICROSTRIP::SynthesizeWidth() const
{
const double e_r = GetParameter( TCP::EPSILONR );
const double a = ( ( GetParameter( TCP::Z0 ) / TC::ZF0 / 2 / M_PI ) * sqrt( ( e_r + 1 ) / 2. ) )
+ ( ( e_r - 1 ) / ( e_r + 1 ) * ( 0.23 + ( 0.11 / e_r ) ) );
const double b = TC::ZF0 / 2 * M_PI / ( GetParameter( TCP::Z0 ) * sqrt( e_r ) );
double w_h;
if( a > 1.52 )
{
w_h = 8 * exp( a ) / ( exp( 2. * a ) - 2 );
}
else
{
w_h = ( 2. / M_PI )
* ( b - 1. - log( ( 2 * b ) - 1. )
+ ( ( e_r - 1 ) / ( 2 * e_r ) ) * ( log( b - 1. ) + 0.39 - 0.61 / e_r ) );
}
double width;
if( GetParameter( TCP::H ) > 0.0 )
width = w_h * GetParameter( TCP::H );
else
width = 0;
return width;
}
double MICROSTRIP::Z0_dispersion( double u, double e_r, double e_r_eff_0, double e_r_eff_f, double f_n )
{
const double R_1 = 0.03891 * pow( e_r, 1.4 );
const double R_2 = 0.267 * pow( u, 7.0 );
const double R_3 = 4.766 * exp( -3.228 * pow( u, 0.641 ) );
const double R_4 = 0.016 + pow( 0.0514 * e_r, 4.524 );
const double R_5 = pow( f_n / 28.843, 12.0 );
const double R_6 = 22.2 * pow( u, 1.92 );
const double R_7 = 1.206 - 0.3144 * exp( -R_1 ) * ( 1.0 - exp( -R_2 ) );
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 ) ) );
double tmpf = pow( e_r - 1.0, 6.0 );
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 ) )
* ( tmpf / ( 1.0 + 10.0 * tmpf ) );
const double R_10 = 0.00044 * pow( e_r, 2.136 ) + 0.0184;
tmpf = pow( f_n / 19.47, 6.0 );
const double R_11 = tmpf / ( 1.0 + 0.0962 * tmpf );
const double R_12 = 1.0 / ( 1.0 + 0.00245 * u * u );
const double R_13 = 0.9408 * pow( e_r_eff_f, R_8 ) - 0.9603;
const double R_14 = ( 0.9408 - R_9 ) * pow( e_r_eff_0, R_8 ) - 0.9603;
const double R_15 = 0.707 * R_10 * pow( f_n / 12.3, 1.097 );
const double R_16 = 1.0 + 0.0503 * e_r * e_r * R_11 * ( 1.0 - exp( -pow( u / 15.0, 6.0 ) ) );
const double R_17 = R_7 * ( 1.0 - 1.1241 * ( R_12 / R_16 ) * exp( -0.026 * pow( f_n, 1.15656 ) - R_15 ) );
return pow( R_13 / R_14, R_17 );
}
double MICROSTRIP::Z0_homogeneous( double u )
{
const double freq = 6.0 + ( 2.0 * M_PI - 6.0 ) * exp( -pow( 30.666 / u, 0.7528 ) );
return ( TC::ZF0 / ( 2.0 * M_PI ) ) * log( freq / u + sqrt( 1.0 + 4.0 / ( u * u ) ) );
}
double MICROSTRIP::delta_Z0_cover( double u, double h2h )
{
const double h2hp1 = 1.0 + h2h;
const double P = 270.0 * ( 1.0 - tanh( 1.192 + 0.706 * sqrt( h2hp1 ) - 1.389 / h2hp1 ) );
const double Q = 1.0109 - atanh( ( 0.012 * u + 0.177 * u * u - 0.027 * u * u * u ) / ( h2hp1 * h2hp1 ) );
return P * Q;
}
double MICROSTRIP::filling_factor( double u, double e_r )
{
const double u2 = u * u;
const double u3 = u2 * u;
const double u4 = u3 * u;
const double a = 1.0 + log( ( u4 + u2 / 2704 ) / ( u4 + 0.432 ) ) / 49.0 + log( 1.0 + u3 / 5929.741 ) / 18.7;
const double b = 0.564 * pow( ( e_r - 0.9 ) / ( e_r + 3.0 ), 0.053 );
return pow( 1.0 + 10.0 / u, -a * b );
}
double MICROSTRIP::delta_q_cover( double h2h )
{
return tanh( 1.043 + 0.121 * h2h - 1.164 / h2h );
}
double MICROSTRIP::delta_q_thickness( double u, double t_h )
{
return ( 2.0 * log( 2.0 ) / M_PI ) * ( t_h / sqrt( u ) );
}
double MICROSTRIP::e_r_effective( double e_r, double q )
{
return 0.5 * ( e_r + 1.0 ) + 0.5 * q * ( e_r - 1.0 );
}
double MICROSTRIP::delta_u_thickness( double u, double t_h, double e_r )
{
double delta_u;
if( t_h > 0.0 )
{
/* correction for thickness for a homogeneous microstrip */
delta_u = ( t_h / M_PI ) * log( 1.0 + ( 4.0 * M_E ) * pow( tanh( sqrt( 6.517 * u ) ), 2.0 ) / t_h );
/* correction for strip on a substrate with relative permettivity e_r */
delta_u = 0.5 * delta_u * ( 1.0 + 1.0 / cosh( sqrt( e_r - 1.0 ) ) );
}
else
{
delta_u = 0.0;
}
return delta_u;
}
double MICROSTRIP::e_r_dispersion( double u, double e_r, double f_n )
{
const double P_1 =
0.27488 + u * ( 0.6315 + 0.525 / pow( 1.0 + 0.0157 * f_n, 20.0 ) ) - 0.065683 * exp( -8.7513 * u );
const double P_2 = 0.33622 * ( 1.0 - exp( -0.03442 * e_r ) );
const double P_3 = 0.0363 * exp( -4.6 * u ) * ( 1.0 - exp( -pow( f_n / 38.7, 4.97 ) ) );
const double P_4 = 1.0 + 2.751 * ( 1.0 - exp( -pow( e_r / 15.916, 8.0 ) ) );
return P_1 * P_2 * pow( ( P_3 * P_4 + 0.1844 ) * f_n, 1.5763 );
}
double MICROSTRIP::conductor_losses() const
{
double alpha_c;
const double e_r_eff_0 = er_eff_0;
const double delta = GetParameter( TCP::SKIN_DEPTH );
if( GetParameter( TCP::FREQUENCY ) > 0.0 )
{
/* current distribution factor */
const double K = exp( -1.2 * pow( Z0_h_1 / TC::ZF0, 0.7 ) );
/* skin resistance */
double R_s = 1.0 / ( GetParameter( TCP::SIGMA ) * delta );
/* correction for surface roughness */
R_s *= 1.0 + ( ( 2.0 / M_PI ) * atan( 1.40 * pow( ( GetParameter( TCP::ROUGH ) / delta ), 2.0 ) ) );
/* strip inductive quality factor */
const double Q_c = ( M_PI * Z0_h_1 * GetParameter( TCP::PHYS_WIDTH ) * GetParameter( TCP::FREQUENCY ) )
/ ( R_s * TC::C0 * K );
alpha_c = ( 20.0 * M_PI / log( 10.0 ) ) * GetParameter( TCP::FREQUENCY ) * sqrt( e_r_eff_0 ) / ( TC::C0 * Q_c );
}
else
{
alpha_c = 0.0;
}
return alpha_c;
}
double MICROSTRIP::dielectric_losses() const
{
const double e_r = GetParameter( TCP::EPSILONR );
const double e_r_eff_0 = er_eff_0;
return ( 20.0 * M_PI / log( 10.0 ) ) * ( GetParameter( TCP::FREQUENCY ) / TC::C0 ) * ( e_r / sqrt( e_r_eff_0 ) )
* ( ( e_r_eff_0 - 1.0 ) / ( e_r - 1.0 ) ) * GetParameter( TCP::TAND );
}
void MICROSTRIP::microstrip_Z0()
{
const double e_r = GetParameter( TCP::EPSILONR );
const double h2 = GetParameter( TCP::H_T );
const double h2h = h2 / GetParameter( TCP::H );
double u = GetParameter( TCP::PHYS_WIDTH ) / GetParameter( TCP::H );
const double t_h = GetParameter( TCP::T ) / GetParameter( TCP::H );
/* compute normalized width correction for e_r = 1.0 */
const double delta_u_1 = delta_u_thickness( u, t_h, 1.0 );
/* compute homogeneous stripline impedance */
Z0_h_1 = Z0_homogeneous( u + delta_u_1 );
/* compute normalized width correction */
const double delta_u_r = delta_u_thickness( u, t_h, e_r );
u += delta_u_r;
/* compute homogeneous stripline impedance */
const double Z0_h_r = Z0_homogeneous( u );
/* filling factor, with width corrected for thickness */
const double q_inf = filling_factor( u, e_r );
/* cover effect */
const double q_c = delta_q_cover( h2h );
/* thickness effect */
const double q_t = delta_q_thickness( u, t_h );
/* resultant filling factor */
const double q = ( q_inf - q_t ) * q_c;
/* e_r corrected for thickness and non-homogeneous material */
const double e_r_eff_t = e_r_effective( e_r, q );
/* effective dielectric constant */
const double e_r_eff = e_r_eff_t * pow( Z0_h_1 / Z0_h_r, 2.0 );
/* characteristic impedance, corrected for thickness, cover */
/* and non-homogeneous material */
SetParameter( TCP::Z0, Z0_h_r / sqrt( e_r_eff_t ) );
w_eff = u * GetParameter( TCP::H );
er_eff_0 = e_r_eff;
Z0_0 = GetParameter( TCP::Z0 );
}
void MICROSTRIP::dispersion()
{
const double e_r = GetParameter( TCP::EPSILONR );
const double e_r_eff_0 = er_eff_0;
const double u = GetParameter( TCP::PHYS_WIDTH ) / GetParameter( TCP::H );
/* normalized frequency [GHz * mm] */
const double f_n = GetParameter( TCP::FREQUENCY ) * GetParameter( TCP::H ) / 1e06;
const double P = e_r_dispersion( u, e_r, f_n );
/* effective dielectric constant corrected for dispersion */
const double e_r_eff_f = e_r - ( e_r - e_r_eff_0 ) / ( 1.0 + P );
const double D = Z0_dispersion( u, e_r, e_r_eff_0, e_r_eff_f, f_n );
const double Z0_f = Z0_0 * D;
SetParameter( TCP::UNIT_PROP_DELAY, UnitPropagationDelay( e_r_eff_f ) );
SetParameter( TCP::EPSILON_EFF, e_r_eff_f );
SetParameter( TCP::Z0, Z0_f );
}
void MICROSTRIP::attenuation()
{
SetParameter( TCP::SKIN_DEPTH, SkinDepth() );
SetParameter( TCP::ATTEN_COND, conductor_losses() * GetParameter( TCP::PHYS_LEN ) );
SetParameter( TCP::ATTEN_DILECTRIC, dielectric_losses() * GetParameter( TCP::PHYS_LEN ) );
}
void MICROSTRIP::mur_eff_ms()
{
const double mur = GetParameter( TCP::MUR );
const double h = GetParameter( TCP::H );
const double w = GetParameter( TCP::PHYS_WIDTH );
mur_eff = ( 2.0 * mur ) / ( ( 1.0 + mur ) + ( ( 1.0 - mur ) * pow( ( 1.0 + ( 10.0 * h / w ) ), -0.5 ) ) );
}
void MICROSTRIP::line_angle()
{
double e_r_eff = GetParameter( TCP::EPSILON_EFF );
// Velocity
double v = TC::C0 / sqrt( e_r_eff * mur_eff );
// Wavelength
double lambda_g = v / GetParameter( TCP::FREQUENCY );
// Electrical angles (rad)
SetParameter( TCP::ANG_L, 2.0 * M_PI * GetParameter( TCP::PHYS_LEN ) / lambda_g );
}

View File

@ -0,0 +1,118 @@
/*
* Copyright (C) 2001 Gopal Narayanan <gopal@astro.umass.edu>
* Copyright (C) 2002 Claudio Girardi <claudio.girardi@ieee.org>
* Copyright (C) 2005, 2006 Stefan Jahn <stefan@lkcc.org>
* Modified for Kicad: 2018 Jean-Pierre Charras <jp.charras at wanadoo.fr>
* Copyright The KiCad Developers, see AUTHORS.txt for contributors.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this package; see the file COPYING. If not, write to
* the Free Software Foundation, Inc., 51 Franklin Street - Fifth Floor,
* Boston, MA 02110-1301, USA.
*/
#ifndef TRANSLINE_CALCULATIONS_MICROSTRIP_H
#define TRANSLINE_CALCULATIONS_MICROSTRIP_H
#include <transline_calculations/transline_calculation_base.h>
class MICROSTRIP : public TRANSLINE_CALCULATION_BASE
{
using TCP = TRANSLINE_PARAMETERS;
public:
MICROSTRIP() :
TRANSLINE_CALCULATION_BASE( { TCP::EPSILONR, TCP::H_T, TCP::H, TCP::PHYS_WIDTH, TCP::T, TCP::Z0,
TCP::FREQUENCY, TCP::EPSILON_EFF, TCP::SKIN_DEPTH, TCP::SIGMA, TCP::ROUGH,
TCP::TAND, TCP::PHYS_LEN, TCP::MUR, TCP::MURC, TCP::ANG_L,
TCP::UNIT_PROP_DELAY, TCP::ATTEN_COND, TCP::ATTEN_DILECTRIC } )
{
}
friend class COUPLED_MICROSTRIP;
/// Analyse track geometry parameters to output Z0 and Ang_L
void Analyse() override;
/// Synthesis track geometry parameters to match given Z0
bool Synthesize( SYNTHESIZE_OPTS aOpts ) override;
private:
/// Sets the output values and status following analysis
void SetAnalysisResults() override;
/// Sets the output values and status following synthesis
void SetSynthesisResults() override;
/// Calculates the width with the current set of parameters
double SynthesizeWidth() const;
/// Calculates the dispersion correction factor for the characteristic impedance static
static double Z0_dispersion( double, double, double, double, double );
/// Calculates the impedance for a stripline in a homogeneous medium, without cover effects
static double Z0_homogeneous( double );
/// Calculates the cover effect on impedance for a stripline in a homogeneous medium
static double delta_Z0_cover( double, double );
/// Calculates the filling factor for a microstrip without cover and zero conductor thickness
static double filling_factor( double, double );
/// Calculates the cover effect on filling factor
static double delta_q_cover( double );
/// Calculates the thickness effect on filling factor
static double delta_q_thickness( double, double );
/// Calculates effective dielectric constant from material e_r and filling factor
static double e_r_effective( double, double );
/// Calculates the thickness effect on normalized width
static double delta_u_thickness( double, double, double );
/// Calculates the dispersion correction factor for the effective permeability
static double e_r_dispersion( double, double, double );
/// Calculate the microstrip conductor losses per unit
double conductor_losses() const;
/// Calculates the microstrip dielectric losses per unit
double dielectric_losses() const;
/// Calculates the microstrip static impedance
void microstrip_Z0();
/// Calculates frequency dependent parameters of the microstrip
void dispersion();
/// Calculates the attenuation of the microstrip
void attenuation();
/// Calculates the effective magnetic permeability
void mur_eff_ms();
/// Calculates microstrip length in radians
void line_angle();
double Z0_0{ 0.0 }; ///< static characteristic impedance
double er_eff_0{ 0.0 }; ///< Static effective dielectric constant
double mur_eff{ 0.0 }; ///< Effective mag. permeability
double w_eff{ 0.0 }; ///< Effective width of line
double Z0_h_1{ 0.0 }; ///< homogeneous stripline impedance
};
#endif //TRANSLINE_CALCULATIONS_MICROSTRIP_H

View File

@ -0,0 +1,172 @@
/*
* Copyright (C) 2001 Gopal Narayanan <gopal@astro.umass.edu>
* Copyright (C) 2002 Claudio Girardi <claudio.girardi@ieee.org>
* Copyright (C) 2005, 2006 Stefan Jahn <stefan@lkcc.org>
* Modified for Kicad: 2018 Jean-Pierre Charras <jp.charras at wanadoo.fr>
* Copyright The KiCad Developers, see AUTHORS.txt for contributors.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this package; see the file COPYING. If not, write to
* the Free Software Foundation, Inc., 51 Franklin Street - Fifth Floor,
* Boston, MA 02110-1301, USA.
*/
#include <transline_calculations/stripline.h>
#include <transline_calculations/units.h>
namespace TC = TRANSLINE_CALCULATIONS;
using TCP = TRANSLINE_PARAMETERS;
void STRIPLINE::Analyse()
{
SetParameter( TCP::SKIN_DEPTH, SkinDepth() );
SetParameter( TCP::EPSILON_EFF, GetParameter( TCP::EPSILONR ) ); // no dispersion
double ac1, ac2;
double t = GetParameter( TCP::T );
double a = GetParameter( TCP::STRIPLINE_A );
double h = GetParameter( TCP::H );
SetParameter( TCP::Z0,
2.0 / ( 1.0 / lineImpedance( 2.0 * a + t, ac1 ) + 1.0 / lineImpedance( 2.0 * ( h - a ) - t, ac2 ) ) );
SetParameter( TCP::LOSS_CONDUCTOR, GetParameter( TCP::PHYS_LEN ) * ( ac1 + ac2 ) );
SetParameter( TCP::LOSS_DIELECTRIC, TC::LOG2DB * GetParameter( TCP::PHYS_LEN ) * ( M_PI / TC::C0 )
* GetParameter( TCP::FREQUENCY ) * sqrt( GetParameter( TCP::EPSILONR ) )
* GetParameter( TCP::TAND ) );
SetParameter( TCP::ANG_L, 2.0 * M_PI * GetParameter( TCP::PHYS_LEN ) * sqrt( GetParameter( TCP::EPSILONR ) )
* GetParameter( TCP::FREQUENCY ) / TC::C0 ); // in radians
unit_prop_delay = UnitPropagationDelay( GetParameter( TCP::EPSILON_EFF ) );
}
bool STRIPLINE::Synthesize( const SYNTHESIZE_OPTS aOpts )
{
return MinimiseZ0Error1D( TCP::PHYS_WIDTH, TCP::Z0 );
}
void STRIPLINE::SetAnalysisResults()
{
SetAnalysisResult( TCP::EPSILON_EFF, GetParameter( TCP::EPSILON_EFF ) );
SetAnalysisResult( TCP::UNIT_PROP_DELAY, unit_prop_delay );
SetAnalysisResult( TCP::LOSS_CONDUCTOR, GetParameter( TCP::LOSS_CONDUCTOR ) );
SetAnalysisResult( TCP::LOSS_DIELECTRIC, GetParameter( TCP::LOSS_DIELECTRIC ) );
SetAnalysisResult( TCP::SKIN_DEPTH, GetParameter( TCP::SKIN_DEPTH ) );
const double Z0 = GetParameter( TCP::Z0 );
const double ANG_L = GetParameter( TCP::ANG_L );
const double L = GetParameter( TCP::PHYS_LEN );
const double W = GetParameter( TCP::PHYS_WIDTH );
const bool Z0_invalid = !std::isfinite( Z0 ) || Z0 < 0;
const bool ANG_L_invalid = !std::isfinite( ANG_L ) || ANG_L < 0;
const bool L_invalid = !std::isfinite( L ) || L < 0;
const bool W_invalid = !std::isfinite( W ) || W <= 0;
bool invalid = false;
if( GetParameter( TCP::STRIPLINE_A ) + GetParameter( TCP::T ) >= GetParameter( TCP::H ) )
invalid = true;
SetAnalysisResult( TCP::Z0, Z0, Z0_invalid || invalid ? TRANSLINE_STATUS::ERROR : TRANSLINE_STATUS::OK );
SetAnalysisResult( TCP::ANG_L, ANG_L, ANG_L_invalid ? TRANSLINE_STATUS::ERROR : TRANSLINE_STATUS::OK );
SetAnalysisResult( TCP::PHYS_LEN, L, L_invalid ? TRANSLINE_STATUS::WARNING : TRANSLINE_STATUS::OK );
SetAnalysisResult( TCP::PHYS_WIDTH, W, W_invalid ? TRANSLINE_STATUS::WARNING : TRANSLINE_STATUS::OK );
SetAnalysisResult( TCP::STRIPLINE_A, GetParameter( TCP::STRIPLINE_A ),
invalid ? TRANSLINE_STATUS::WARNING : TRANSLINE_STATUS::OK );
SetAnalysisResult( TCP::T, GetParameter( TCP::T ), invalid ? TRANSLINE_STATUS::WARNING : TRANSLINE_STATUS::OK );
SetAnalysisResult( TCP::H, GetParameter( TCP::H ), invalid ? TRANSLINE_STATUS::WARNING : TRANSLINE_STATUS::OK );
SetAnalysisResult( TCP::Z0, GetParameter( TCP::Z0 ), invalid ? TRANSLINE_STATUS::WARNING : TRANSLINE_STATUS::OK );
}
void STRIPLINE::SetSynthesisResults()
{
SetSynthesisResult( TCP::EPSILON_EFF, GetParameter( TCP::EPSILON_EFF ) );
SetSynthesisResult( TCP::UNIT_PROP_DELAY, unit_prop_delay );
SetSynthesisResult( TCP::LOSS_CONDUCTOR, GetParameter( TCP::LOSS_CONDUCTOR ) );
SetSynthesisResult( TCP::LOSS_DIELECTRIC, GetParameter( TCP::LOSS_DIELECTRIC ) );
SetSynthesisResult( TCP::SKIN_DEPTH, GetParameter( TCP::SKIN_DEPTH ) );
const double Z0 = GetParameter( TCP::Z0 );
const double ANG_L = GetParameter( TCP::ANG_L );
const double L = GetParameter( TCP::PHYS_LEN );
const double W = GetParameter( TCP::PHYS_WIDTH );
const bool Z0_invalid = !std::isfinite( Z0 ) || Z0 < 0;
const bool ANG_L_invalid = !std::isfinite( ANG_L ) || ANG_L < 0;
const bool L_invalid = !std::isfinite( L ) || L < 0;
const bool W_invalid = !std::isfinite( W ) || W <= 0;
bool invalid = false;
if( GetParameter( TCP::STRIPLINE_A ) + GetParameter( TCP::T ) >= GetParameter( TCP::H ) )
invalid = true;
SetSynthesisResult( TCP::Z0, Z0, Z0_invalid ? TRANSLINE_STATUS::WARNING : TRANSLINE_STATUS::OK );
SetSynthesisResult( TCP::ANG_L, ANG_L, ANG_L_invalid ? TRANSLINE_STATUS::WARNING : TRANSLINE_STATUS::OK );
SetSynthesisResult( TCP::PHYS_LEN, L, L_invalid ? TRANSLINE_STATUS::ERROR : TRANSLINE_STATUS::OK );
SetSynthesisResult( TCP::PHYS_WIDTH, W, W_invalid || invalid ? TRANSLINE_STATUS::ERROR : TRANSLINE_STATUS::OK );
SetSynthesisResult( TCP::STRIPLINE_A, GetParameter( TCP::STRIPLINE_A ),
invalid ? TRANSLINE_STATUS::WARNING : TRANSLINE_STATUS::OK );
SetSynthesisResult( TCP::T, GetParameter( TCP::T ), invalid ? TRANSLINE_STATUS::WARNING : TRANSLINE_STATUS::OK );
SetSynthesisResult( TCP::H, GetParameter( TCP::H ), invalid ? TRANSLINE_STATUS::WARNING : TRANSLINE_STATUS::OK );
}
double STRIPLINE::lineImpedance( double aHeight, double& aAc ) const
{
double ZL;
const double hmt = aHeight - GetParameter( TCP::T );
aAc = sqrt( GetParameter( TCP::FREQUENCY ) / GetParameter( TCP::SIGMA ) / 17.2 );
if( GetParameter( TCP::PHYS_WIDTH ) / hmt >= 0.35 )
{
ZL = GetParameter( TCP::PHYS_WIDTH )
+ ( 2.0 * aHeight * log( ( 2.0 * aHeight - GetParameter( TCP::T ) ) / hmt )
- GetParameter( TCP::T ) * log( aHeight * aHeight / hmt / hmt - 1.0 ) )
/ M_PI;
ZL = TC::ZF0 * hmt / sqrt( GetParameter( TCP::EPSILONR ) ) / 4.0 / ZL;
aAc *= 2.02e-6 * GetParameter( TCP::EPSILONR ) * ZL / hmt;
aAc *= 1.0 + 2.0 * GetParameter( TCP::PHYS_WIDTH ) / hmt
+ ( aHeight + GetParameter( TCP::T ) ) / hmt / M_PI
* log( 2.0 * aHeight / GetParameter( TCP::T ) - 1.0 );
}
else
{
double tdw = GetParameter( TCP::T ) / GetParameter( TCP::PHYS_WIDTH );
if( GetParameter( TCP::T ) / GetParameter( TCP::PHYS_WIDTH ) > 1.0 )
tdw = GetParameter( TCP::PHYS_WIDTH ) / GetParameter( TCP::T );
double de = 1.0 + tdw / M_PI * ( 1.0 + log( 4.0 * M_PI / tdw ) ) + 0.236 * pow( tdw, 1.65 );
if( GetParameter( TCP::T ) / GetParameter( TCP::PHYS_WIDTH ) > 1.0 )
de *= GetParameter( TCP::T ) / 2.0;
else
de *= GetParameter( TCP::PHYS_WIDTH ) / 2.0;
ZL = TC::ZF0 / 2.0 / M_PI / sqrt( GetParameter( TCP::EPSILONR ) ) * log( 4.0 * aHeight / M_PI / de );
aAc *= 0.01141 / ZL / de;
aAc *= de / aHeight + 0.5 + tdw / 2.0 / M_PI + 0.5 / M_PI * log( 4.0 * M_PI / tdw ) + 0.1947 * pow( tdw, 0.65 )
- 0.0767 * pow( tdw, 1.65 );
}
return ZL;
}

View File

@ -0,0 +1,64 @@
/*
* Copyright (C) 2001 Gopal Narayanan <gopal@astro.umass.edu>
* Copyright (C) 2002 Claudio Girardi <claudio.girardi@ieee.org>
* Copyright (C) 2005, 2006 Stefan Jahn <stefan@lkcc.org>
* Modified for Kicad: 2018 Jean-Pierre Charras <jp.charras at wanadoo.fr>
* Copyright The KiCad Developers, see AUTHORS.txt for contributors.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this package; see the file COPYING. If not, write to
* the Free Software Foundation, Inc., 51 Franklin Street - Fifth Floor,
* Boston, MA 02110-1301, USA.
*/
#ifndef TRANSLINE_CALCULATIONS_STRIPLINE_H
#define TRANSLINE_CALCULATIONS_STRIPLINE_H
#include <transline_calculations/transline_calculation_base.h>
class STRIPLINE : public TRANSLINE_CALCULATION_BASE
{
using TCP = TRANSLINE_PARAMETERS;
public:
STRIPLINE() :
TRANSLINE_CALCULATION_BASE( { TCP::SKIN_DEPTH, TCP::EPSILON_EFF, TCP::EPSILONR, TCP::T, TCP::STRIPLINE_A,
TCP::H, TCP::Z0, TCP::LOSS_CONDUCTOR, TCP::PHYS_LEN, TCP::LOSS_DIELECTRIC,
TCP::FREQUENCY, TCP::TAND, TCP::PHYS_WIDTH, TCP::UNIT_PROP_DELAY, TCP::ANG_L,
TCP::SIGMA, TCP::MURC } )
{
}
/// Analyse track geometry parameters to output Z0 and Ang_L
void Analyse() override;
/// Synthesis track geometry parameters to match given Z0
bool Synthesize( SYNTHESIZE_OPTS aOpts ) override;
private:
/// Sets the output values and status following analysis
void SetAnalysisResults() override;
/// Sets the output values and status following synthesis
void SetSynthesisResults() override;
/// Calculate characteristic impedance and conductor loss (in db/meter)
double lineImpedance( double aHeight, double& aAc ) const;
double unit_prop_delay;
};
#endif //TRANSLINE_CALCULATIONS_STRIPLINE_H

View File

@ -0,0 +1,225 @@
/*
* Copyright The KiCad Developers, see AUTHORS.txt for contributors.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this package; see the file COPYING. If not, write to
* the Free Software Foundation, Inc., 51 Franklin Street - Fifth Floor,
* Boston, MA 02110-1301, USA.
*/
#include <transline_calculations/units.h>
#include <transline_calculations/transline_calculation_base.h>
using TCP = TRANSLINE_PARAMETERS;
namespace TC = TRANSLINE_CALCULATIONS;
void TRANSLINE_CALCULATION_BASE::InitProperties( const std::initializer_list<TRANSLINE_PARAMETERS>& aParams )
{
for( const TRANSLINE_PARAMETERS& param : aParams )
m_parameters[param] = 0.0;
}
std::unordered_map<TRANSLINE_PARAMETERS, std::pair<double, TRANSLINE_STATUS>>&
TRANSLINE_CALCULATION_BASE::GetAnalysisResults()
{
SetAnalysisResults();
return m_analysisStatus;
}
std::unordered_map<TRANSLINE_PARAMETERS, std::pair<double, TRANSLINE_STATUS>>&
TRANSLINE_CALCULATION_BASE::GetSynthesisResults()
{
SetSynthesisResults();
return m_synthesisStatus;
}
void TRANSLINE_CALCULATION_BASE::SetAnalysisResult( const TRANSLINE_PARAMETERS aParam, const double aValue,
const TRANSLINE_STATUS aStatus )
{
m_analysisStatus[aParam] = { aValue, aStatus };
}
void TRANSLINE_CALCULATION_BASE::SetSynthesisResult( const TRANSLINE_PARAMETERS aParam, const double aValue,
const TRANSLINE_STATUS aStatus )
{
m_synthesisStatus[aParam] = { aValue, aStatus };
}
bool TRANSLINE_CALCULATION_BASE::MinimiseZ0Error1D( const TRANSLINE_PARAMETERS aOptimise,
const TRANSLINE_PARAMETERS aMeasure )
{
double& var = GetParameterRef( aOptimise );
double& Z0_param = GetParameterRef( aMeasure );
double& ANG_L_param = GetParameterRef( TCP::ANG_L );
if( !std::isfinite( Z0_param ) )
{
var = NAN;
return false;
}
if( ( !std::isfinite( var ) ) || ( var == 0 ) )
var = 0.001;
/* required value of Z0 */
double Z0_dest = Z0_param;
/* required value of angl_l */
double angl_l_dest = ANG_L_param;
/* Newton's method */
int iteration = 0;
/* compute parameters */
Analyse();
double Z0_current = Z0_param;
double error = fabs( Z0_dest - Z0_current );
while( error > m_maxError )
{
iteration++;
double increment = var / 100.0;
var += increment;
/* compute parameters */
Analyse();
double Z0_result = Z0_param;
// f(w(n)) = Z0 - Z0(w(n))
// f'(w(n)) = -f'(Z0(w(n)))
// f'(Z0(w(n))) = (Z0(w(n)) - Z0(w(n+delw))/delw
// w(n+1) = w(n) - f(w(n))/f'(w(n))
double slope = ( Z0_result - Z0_current ) / increment;
slope = ( Z0_dest - Z0_current ) / slope - increment;
var += slope;
if( var <= 0.0 )
var = increment;
/* find new error */
/* compute parameters */
Analyse();
Z0_current = Z0_param;
error = fabs( Z0_dest - Z0_current );
if( iteration > 250 )
break;
}
/* Compute one last time, but with correct length */
Z0_param = Z0_dest;
ANG_L_param = angl_l_dest;
SetParameter( TCP::PHYS_LEN, TC::C0 / GetParameter( TCP::FREQUENCY ) / sqrt( GetParameter( TCP::EPSILON_EFF ) )
* ANG_L_param / 2.0 / M_PI ); /* in m */
Analyse();
/* Restore parameters */
Z0_param = Z0_dest;
ANG_L_param = angl_l_dest;
SetParameter( TCP::PHYS_LEN, TC::C0 / GetParameter( TCP::FREQUENCY ) / sqrt( GetParameter( TCP::EPSILON_EFF ) )
* ANG_L_param / 2.0 / M_PI ); /* in m */
return error <= m_maxError;
}
double TRANSLINE_CALCULATION_BASE::SkinDepth() const
{
double depth = 1.0
/ sqrt( M_PI * GetParameter( TCP::FREQUENCY ) * GetParameter( TCP::MURC )
* TRANSLINE_CALCULATIONS::MU0 * GetParameter( TCP::SIGMA ) );
return depth;
}
double TRANSLINE_CALCULATION_BASE::UnitPropagationDelay( const double aEpsilonEff )
{
return std::sqrt( aEpsilonEff ) * ( 1.0e10 / 2.99e8 );
}
std::pair<double, double> TRANSLINE_CALCULATION_BASE::EllipticIntegral( const double arg )
{
static constexpr double NR_EPSI = 2.2204460492503131e-16;
int iMax = 16;
double k = 0.0, e = 0.0;
if( arg == 1.0 )
{
k = INFINITY; // infinite
e = 0;
}
else if( std::isinf( arg ) && arg < 0 )
{
k = 0;
e = INFINITY; // infinite
}
else
{
double a, b, c, fr, s, fk = 1, fe = 1, t, da = arg;
int i;
if( arg < 0 )
{
fk = 1 / sqrt( 1 - arg );
fe = sqrt( 1 - arg );
da = -arg / ( 1 - arg );
}
a = 1;
b = sqrt( 1 - da );
c = sqrt( da );
fr = 0.5;
s = fr * c * c;
for( i = 0; i < iMax; i++ )
{
t = ( a + b ) / 2;
c = ( a - b ) / 2;
b = sqrt( a * b );
a = t;
fr *= 2;
s += fr * c * c;
if( c / a < NR_EPSI )
break;
}
if( i >= iMax )
{
k = 0;
e = 0;
}
else
{
k = M_PI_2 / a;
e = M_PI_2 * ( 1 - s ) / a;
if( arg < 0 )
{
k *= fk;
e *= fe;
}
}
}
return { k, e };
}

View File

@ -0,0 +1,227 @@
/*
* Copyright The KiCad Developers, see AUTHORS.txt for contributors.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this package; see the file COPYING. If not, write to
* the Free Software Foundation, Inc., 51 Franklin Street - Fifth Floor,
* Boston, MA 02110-1301, USA.
*/
#ifndef TRANSLINE_CALCULATIONS_TRANSLINE_CALCULATION_BASE_H
#define TRANSLINE_CALCULATIONS_TRANSLINE_CALCULATION_BASE_H
#include <unordered_map>
/// All possible parameters used (as inputs or outputs) by the transmission line calculations
enum class TRANSLINE_PARAMETERS : int
{
// The following parameters are accessible from the UI
UNKNOWN_ID = -1,
EPSILONR, // Dielectric constant
TAND, // Dielectric Loss Tangent
RHO, // Conductivity of conductor
H, // Height of substrate
H_T, // Height of top surface
T, // Height of top conductor
PHYS_WIDTH, // Width of trace
PHYS_DIAM_IN, // Inner diameter of cable
PHYS_S, // width of gap between line and ground
PHYS_DIAM_OUT, // Outer diameter of cable
PHYS_LEN, // Length of cable
ROUGH, // Surface roughness
MUR, // Magnetic permeability of substrate
MURC, // magnetic permeability of conductor
FREQUENCY, // Frequency of operation
STRIPLINE_A, // Stripline : distance from track to top plane
TWISTEDPAIR_TWIST, // Twists per length
TWISTEDPAIR_EPSILONR_ENV, // Dielectric constant of environment
Z0, // Characteristic impedance
Z0_E, // Even-mode characteristic impedance
Z0_O, // Odd-mode characteristic impedance
ANG_L, // Electrical length in angle
DUMMY_PRM,
// The following parameters are generated by calculations
SIGMA, // Conductivity of the metal
SKIN_DEPTH, // Skin depth
LOSS_DIELECTRIC, // Loss in dielectric (dB)
LOSS_CONDUCTOR, // Loss in conductors (dB)
CUTOFF_FREQUENCY, // Cutoff frequency for higher order modes
EPSILON_EFF, // Effective dielectric constant
EPSILON_EFF_EVEN, // Even mode effective dielectric constant
EPSILON_EFF_ODD, // Odd mode effective dielectric constant
UNIT_PROP_DELAY, // The unit propagation delay (ps/cm)
UNIT_PROP_DELAY_ODD, // The odd mode unit propagation delay (ps/cm)
UNIT_PROP_DELAY_EVEN, // The even mode unit propagation delay (ps/cm)
ATTEN_COND, // The attenuation of the conductor
ATTEN_COND_EVEN, // The even mode attenuation of the conductor
ATTEN_COND_ODD, // The odd mode attenuation of the conductor
ATTEN_DILECTRIC, // The attenuation of the dilectric
ATTEN_DILECTRIC_EVEN, // The even mode attenuation of the dilectric
ATTEN_DILECTRIC_ODD, // The odd mode attenuation of the dilectric
Z_DIFF, // The differential impedance
EXTRAS_COUNT
};
/// Options for specifying synthesis inputs, targets, or strategies
enum class SYNTHESIZE_OPTS
{
DEFAULT, // Use the default synthesis options for the calculation
FIX_WIDTH, // Fixes the width of a differential pair
FIX_SPACING // Fixes the spacing of a differential pair
};
/// Parameter status values
enum class TRANSLINE_STATUS
{
OK,
WARNING,
ERROR
};
/**
* The base class for all transmission line calculations. This is used by the PCB calculator, and by delay profiles
*/
class TRANSLINE_CALCULATION_BASE
{
public:
/**
* Constructs the transmission line calculation object.
*
* @aParameters all parameters that are used (as inputs or outputs) by the calculation
*/
TRANSLINE_CALCULATION_BASE( std::initializer_list<TRANSLINE_PARAMETERS> aParameters )
{
InitProperties( aParameters );
}
virtual ~TRANSLINE_CALCULATION_BASE() {}
/// Sets the given calculation property
void SetParameter( const TRANSLINE_PARAMETERS aParam, const double aValue ) { m_parameters.at( aParam ) = aValue; }
/// Gets the given calculation property
double GetParameter( const TRANSLINE_PARAMETERS aParam ) const { return m_parameters.at( aParam ); }
/// Adds a constant to the given parameter
double& GetParameterRef( const TRANSLINE_PARAMETERS aParam ) { return m_parameters[aParam]; }
/// Gets the output parameters following analysis
std::unordered_map<TRANSLINE_PARAMETERS, std::pair<double, TRANSLINE_STATUS>>& GetAnalysisResults();
/// Gets the output parameters following synthesis
std::unordered_map<TRANSLINE_PARAMETERS, std::pair<double, TRANSLINE_STATUS>>& GetSynthesisResults();
/// Analyses the transmission line using the current parameter set
virtual void Analyse() = 0;
/// Synthesis the transmission line using the current parameter set target
/// @returns true if the synthesis converged, otherwise false
virtual bool Synthesize( SYNTHESIZE_OPTS aOpts ) = 0;
protected:
/// Initialises the properties used (as inputs or outputs) by the calculation
void InitProperties( const std::initializer_list<TRANSLINE_PARAMETERS>& aParams );
/// Sets values in the output analysis results structure
virtual void SetAnalysisResults() = 0;
/// Sets values in the output synthesis results structure
virtual void SetSynthesisResults() = 0;
/// Sets an analysis result
void SetAnalysisResult( TRANSLINE_PARAMETERS aParam, const double aValue,
const TRANSLINE_STATUS aStatus = TRANSLINE_STATUS::OK );
/// Sets a synthesis result
void SetSynthesisResult( TRANSLINE_PARAMETERS aParam, const double aValue,
const TRANSLINE_STATUS aStatus = TRANSLINE_STATUS::OK );
/**
* minimizeZ0Error1D
*
* Tries to find a parameter that minimizes the error on Z0.
* This function only works with a single parameter.
* Calls @ref Analyse several times until the error is acceptable.
*
* This function does not change Z0 / Angl_L
*
* @param aOptimise Parameter to optimise
* @param aMeasure The parameter to measure / optimise against
* @returns true if error < MAX_ERROR, otherwise false
*/
bool MinimiseZ0Error1D( TRANSLINE_PARAMETERS aOptimise, TRANSLINE_PARAMETERS aMeasure );
/**
* minimizeZ0Error2D
*
* Tries to find the parameters that minimizes the error on Z_Diff.
* This function only works with two parameters.
* Calls @ref Analyse several times until the error is acceptable.
* While the error is unacceptable, changes slightly the parameter.
*
* This function does not change Z0 / Angl_L
*
* @param aParam1 First parameter to optimise
* @param aParam2 Secpmd parameter to optimise
* @returns true if error < MAX_ERROR, otherwise false
*/
bool MinimiseZ0Error2D( TRANSLINE_PARAMETERS aParam1, TRANSLINE_PARAMETERS aParam2 );
/**
* Calculate skin depth
*
* \f$ \frac{1}{\sqrt{ \pi \cdot f \cdot \mu \cdot \sigma }} \f$
*/
double SkinDepth() const;
/**
* Calculates the unit propagation delay (ps/cm) for the given effective permittivity
*
* @aEpsilonEff is the effective permittivity of the material
*/
static double UnitPropagationDelay( double aEpsilonEff );
/**
* Computes the complete elliptic integral of first kind K() and the second kind E() using the
* arithmetic-geometric mean algorithm (AGM) by Abramowitz and Stegun.
*
* @returns std::pair<K, E> where K = first kind integral, E = second kind integral
*/
static std::pair<double, double> EllipticIntegral( double arg );
/// Calculates cosh of the given argument
static double coth( const double x ) { return ( std::exp( 2.0 * x ) + 1.0 ) / ( std::exp( 2.0 * x ) - 1.0 ); }
/// Calculates sech of the given argument
static double sech( const double x ) { return 2.0 / ( std::exp( x ) + std::exp( -x ) ); }
/// All input and output properties used by the calculation
std::unordered_map<TRANSLINE_PARAMETERS, double> m_parameters;
/// Analysis results
std::unordered_map<TRANSLINE_PARAMETERS, std::pair<double, TRANSLINE_STATUS>> m_analysisStatus;
/// Synthesis results
std::unordered_map<TRANSLINE_PARAMETERS, std::pair<double, TRANSLINE_STATUS>> m_synthesisStatus;
/// The maximum error for Z0 optimisations
static constexpr double m_maxError{ 0.000001 };
};
#endif //TRANSLINE_CALCULATIONS_TRANSLINE_CALCULATION_BASE_H

View File

@ -0,0 +1,74 @@
/*
* Copyright (C) 1992-2011 jean-pierre.charras
* Copyright The KiCad Developers, see AUTHORS.txt for contributors.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this package; see the file COPYING. If not, write to
* the Free Software Foundation, Inc., 51 Franklin Street - Fifth Floor,
* Boston, MA 02110-1301, USA.
*
*/
#ifndef TRANSLINE_CALCULATIONS_UNITS_H
#define TRANSLINE_CALCULATIONS_UNITS_H
#include <cmath>
#ifndef HAVE_CMATH_ASINH
inline double asinh( double x )
{
return log( x + sqrt( x * x + 1 ) );
}
#endif
#ifndef HAVE_CMATH_ACOSH
inline double acosh( double x )
{
// must be x>=1, if not return Nan (Not a Number)
if( x < 1.0 )
return sqrt( -1.0 );
// return only the positive result (as sqrt does).
return log( x + sqrt( x * x - 1.0 ) );
}
#endif
#ifndef HAVE_CMATH_ATANH
inline double atanh( double x )
{
// must be x>-1, x<1, if not return Nan (Not a Number)
if( !( x > -1.0 && x < 1.0 ) )
return sqrt( -1.0 );
return log( ( 1.0 + x ) / ( 1.0 - x ) ) / 2.0;
}
#endif
namespace TRANSLINE_CALCULATIONS
{
constexpr double MU0 = 12.566370614e-7; // magnetic constant
constexpr double E0 = 8.854e-12; // permittivity of free space
constexpr double C0 = 299792458.0; // speed of light in vacuum
constexpr double ZF0 = 376.730313668; // wave resistance in vacuum
// const to convert a attenuation / loss from log (Neper) to decibel
// (1 Np = 8.68589 dB)
const double LOG2DB = 20.0 / log( 10.0 );
// ZF0 value update:
// https://physics.nist.gov/cgi-bin/cuu/Value?z0
}; // namespace TRANSLINE_CALCULATIONS
#endif // TRANSLINE_CALCULATIONS_UNITS_H

View File

@ -0,0 +1,72 @@
/*
* Copyright The KiCad Developers, see AUTHORS.txt for contributors.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this package; see the file COPYING. If not, write to
* the Free Software Foundation, Inc., 51 Franklin Street - Fifth Floor,
* Boston, MA 02110-1301, USA.
*/
#ifndef TRANSLINE_CALCULATION_UNITS_SCALES_H
#define TRANSLINE_CALCULATION_UNITS_SCALES_H
namespace TRANSLINE_CALCULATIONS
{
constexpr double UNIT_KM = 1e3; // km to meter
constexpr double UNIT_M = 1; // m to meter
constexpr double UNIT_CM = 1e-2; // cm to meter
constexpr double UNIT_MM = 1e-3; // mm to meter
constexpr double UNIT_MICRON = 1e-6; // um to meter
constexpr double UNIT_INCH = ( 1e-2 * 2.54 ); // inch to meter
constexpr double UNIT_MIL = ( 1e-5 * 2.54 ); // mil (or thou) to meter
constexpr double UNIT_FEET = 0.3048; // feet to meter
constexpr double UNIT_OZSQFT = ( 34.40 * UNIT_MICRON ); // 1 oz/ft^2 is 34.30 microns nominal, 30.90 minimum
constexpr double UNIT_GHZ = 1e9;
constexpr double UNIT_MHZ = 1e6;
constexpr double UNIT_KHZ = 1e3;
constexpr double UNIT_DEGREE = M_PI / 180.0; // degree to radian
constexpr double UNIT_RADIAN = 1.0; // Radian to radian
constexpr double UNIT_OHM = 1.0; // Ohm to Ohm
constexpr double UNIT_KOHM = 1e3; // KOhm to Ohm
constexpr double UNIT_OHM_PER_METER = 1.0; // Ohm per meter to Ohm per meter
constexpr double UNIT_OHM_PER_KILOMETER = 1e-3; // Ohm per kilometer to Ohm per meter
constexpr double UNIT_OHM_PER_FEET = 3.28084; // Ohm per feet to Ohm per meter
constexpr double UNIT_OHM_PER_1000FEET = 3.28084e-3; // Ohm per 1000feet to Ohm per meter
constexpr double UNIT_KILOVOLT = 1e-3; // Kilovolt to Volt
constexpr double UNIT_VOLT = 1.0; // Volt to Volt
constexpr double UNIT_MILLIVOLT = 1e+3; // Millivolt to Volt
constexpr double UNIT_MEGAWATT = 1e-6; // Kilowatt to Watt
constexpr double UNIT_KILOWATT = 1e-3; // Kilowatt to Watt
constexpr double UNIT_WATT = 1.0; // Watt to Watt
constexpr double UNIT_MILLIWATT = 1e+3; // Milliwatt to Watt
constexpr double UNIT_METER_PER_SECOND = 1.0; // meter per second to meter per second
constexpr double UNIT_KILOMETER_PER_HOUR = ( 1 / 3.6 ); // km/h to m/s
constexpr double UNIT_FEET_PER_SECOND = 0.3048; // ft/s to m/s
constexpr double UNIT_MILES_PER_HOUR = 1609.34; // mi/h to m/s
constexpr double UNIT_SECOND = 1.0; // second to second
constexpr double UNIT_MSECOND = 1e-3; // millisecond to second
constexpr double UNIT_USECOND = 1e-6; // microsecond to second
constexpr double UNIT_NSECOND = 1e-9; // nanosecond to second
constexpr double UNIT_PSECOND = 1e-12; // picosecond to second
}; // namespace TRANSLINE_CALCULATIONS
#endif // TRANSLINE_CALCULATION_UNITS_SCALES_H

View File

@ -139,6 +139,7 @@ enum class BITMAPS : unsigned int
copper_layers_setup,
copy,
copy_pad_settings,
coupled_stripline,
cpw,
cpw_back,
cursor,

View File

@ -57,6 +57,7 @@ set( PCB_CALCULATOR_SRCS
transline/coax.cpp
transline/rectwaveguide.cpp
transline/stripline.cpp
transline/c_stripline.cpp
transline/twistedpair.cpp
transline_dlg_funct.cpp
attenuators/attenuator_classes.cpp

View File

@ -37,19 +37,11 @@ PANEL_TRANSLINE::PANEL_TRANSLINE( wxWindow* parent, wxWindowID id, const wxPoint
// Populate transline list ordered like in dialog menu list
const static TRANSLINE_TYPE_ID tltype_list[8] =
{
MICROSTRIP_TYPE,
CPW_TYPE,
GROUNDED_CPW_TYPE,
RECTWAVEGUIDE_TYPE,
COAX_TYPE,
C_MICROSTRIP_TYPE,
STRIPLINE_TYPE,
TWISTEDPAIR_TYPE
};
const static TRANSLINE_TYPE_ID tltype_list[9] = { MICROSTRIP_TYPE, C_MICROSTRIP_TYPE, STRIPLINE_TYPE,
C_STRIPLINE_TYPE, CPW_TYPE, GROUNDED_CPW_TYPE,
RECTWAVEGUIDE_TYPE, COAX_TYPE, TWISTEDPAIR_TYPE };
for( int ii = 0; ii < 8; ii++ )
for( int ii = 0; ii < 9; ii++ )
m_transline_list.push_back( new TRANSLINE_IDENT( tltype_list[ii] ) );
m_EpsilonR_label->SetLabel( wxT( "εr" ) );

View File

@ -20,14 +20,22 @@ PANEL_TRANSLINE_BASE::PANEL_TRANSLINE_BASE( wxWindow* parent, wxWindowID id, con
wxBoxSizer* bLeftSizer;
bLeftSizer = new wxBoxSizer( wxVERTICAL );
wxString m_TranslineSelectionChoices[] = { _("Microstrip Line"), _("Coplanar wave guide"), _("Coplanar wave guide w/ ground plane"), _("Rectangular Waveguide"), _("Coaxial Line"), _("Coupled Microstrip Line"), _("Stripline"), _("Twisted Pair") };
int m_TranslineSelectionNChoices = sizeof( m_TranslineSelectionChoices ) / sizeof( wxString );
m_TranslineSelection = new wxRadioBox( this, wxID_ANY, _("Transmission Line Type"), wxDefaultPosition, wxDefaultSize, m_TranslineSelectionNChoices, m_TranslineSelectionChoices, 1, wxRA_SPECIFY_COLS );
m_TranslineSelection->SetSelection( 1 );
bLeftSizer->Add( m_TranslineSelection, 0, wxTOP|wxRIGHT|wxLEFT|wxEXPAND, 5 );
wxString m_TranslineSelectionChoices[] = { _( "Microstrip Line" ),
_( "Coupled Microstrip Line" ),
_( "Stripline" ),
_( "Coupled Stripline" ),
_( "Coplanar wave guide" ),
_( "Coplanar wave guide w/ ground plane" ),
_( "Rectangular Waveguide" ),
_( "Coaxial Line" ),
_( "Twisted Pair" ) };
int m_TranslineSelectionNChoices = sizeof( m_TranslineSelectionChoices ) / sizeof( wxString );
m_TranslineSelection = new wxRadioBox( this, wxID_ANY, _("Transmission Line Type"), wxDefaultPosition, wxDefaultSize, m_TranslineSelectionNChoices, m_TranslineSelectionChoices, 1, wxRA_SPECIFY_COLS );
m_TranslineSelection->SetSelection( 0 );
bLeftSizer->Add( m_TranslineSelection, 0, wxTOP | wxRIGHT | wxLEFT | wxEXPAND, 5 );
bLeftSizer->Add( 0, 5, 0, wxEXPAND, 5 );
bLeftSizer->Add( 0, 5, 0, wxEXPAND, 5 );
m_translineBitmap = new wxStaticBitmap( this, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxDefaultSize, 0 );
bLeftSizer->Add( m_translineBitmap, 0, wxALIGN_CENTER_HORIZONTAL|wxTOP|wxBOTTOM, 10 );

View File

@ -87,7 +87,7 @@
<property name="caption"></property>
<property name="caption_visible">1</property>
<property name="center_pane">0</property>
<property name="choices">&quot;Microstrip Line&quot; &quot;Coplanar wave guide&quot; &quot;Coplanar wave guide w/ ground plane&quot; &quot;Rectangular Waveguide&quot; &quot;Coaxial Line&quot; &quot;Coupled Microstrip Line&quot; &quot;Stripline&quot; &quot;Twisted Pair&quot;</property>
<property name="choices">&quot;Microstrip Line&quot; &quot;Coupled Microstrip Line&quot; &quot;Stripline&quot; &quot;Coupled Stripline&quot; &quot;Coplanar wave guide&quot; &quot;Coplanar wave guide w/ ground plane&quot; &quot;Rectangular Waveguide&quot; &quot;Coaxial Line&quot; &quot;Twisted Pair&quot;</property>
<property name="close_button">1</property>
<property name="context_help"></property>
<property name="context_menu">1</property>
@ -120,7 +120,7 @@
<property name="pin_button">1</property>
<property name="pos"></property>
<property name="resize">Resizable</property>
<property name="selection">1</property>
<property name="selection">0</property>
<property name="show">1</property>
<property name="size"></property>
<property name="style">wxRA_SPECIFY_COLS</property>

File diff suppressed because it is too large Load Diff

View File

@ -4,6 +4,7 @@
* Copyright (C) 2002 Claudio Girardi <in3otd@qsl.net>
* Copyright (C) 2005 Stefan Jahn <stefan@lkcc.org>
* Modifications for Kicad: 2015 Jean-Pierre Charras
* Copyright The KiCad Developers, see AUTHORS.txt for contributors.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
@ -21,81 +22,28 @@
* Boston, MA 02110-1301, USA.
*/
#ifndef _C_MICROSTRIP_H_
#define _C_MICROSTRIP_H_
#include "transline/microstrip.h"
#include "transline/transline.h"
#include <transline_calculations/coupled_microstrip.h>
class C_MICROSTRIP : public TRANSLINE
{
public:
C_MICROSTRIP();
~C_MICROSTRIP();
private:
double h; // height of substrate
double ht; // height to the top of box
double t; // thickness of top metal
double rough; // Roughness of top metal
double w; // width of lines
double w_t_e; // even-mode thickness-corrected line width
double w_t_o; // odd-mode thickness-corrected line width
double l; // length of lines
double s; // spacing of lines
double Z0_e_0; // static even-mode impedance
double Z0_o_0; // static odd-mode impedance
double Zdiff; // differential impedance
double Z0e; // even-mode impedance
double Z0o; // odd-mode impedance
double c_e; // even-mode capacitance
double c_o; // odd-mode capacitance
double ang_l_e; // even-mode electrical length in angle
double ang_l_o; // odd-mode electrical length in angle
double er_eff_e; // even-mode effective dielectric constant
double er_eff_o; // odd-mode effective dielectric constant
double prop_delay_e; // even-mode unit propagation delay (ps/cm)
double prop_delay_o; // odd-mode unit propagation delay (ps/cm)
double er_eff_e_0; // static even-mode effective dielectric constant
double er_eff_o_0; // static odd-mode effective dielectric constant
double w_eff; // Effective width of line
double atten_dielectric_e; // even-mode dielectric losses (dB)
double atten_cond_e; // even-mode conductors losses (dB)
double atten_dielectric_o; // odd-mode dielectric losses (dB)
double atten_cond_o; // odd-mode conductors losses (dB)
void calcAnalyze() override;
void calcSynthesize() override;
void showAnalyze() override;
void showSynthesize() override;
void show_results() override;
void getProperties() override;
private:
double delta_u_thickness_single( double, double );
void delta_u_thickness();
void compute_single_line();
double filling_factor_even( double, double, double );
double filling_factor_odd( double, double, double );
double delta_q_cover_even( double );
double delta_q_cover_odd( double );
void er_eff_static();
double delta_Z0_even_cover( double, double, double );
double delta_Z0_odd_cover( double, double, double );
void Z0_even_odd();
void er_eff_freq();
void conductor_losses();
void dielectric_losses();
void attenuation();
void line_angle();
void diff_impedance();
void syn_err_fun( double*, double*, double, double, double, double, double );
void synth_width();
void Z0_dispersion();
void calcAnalyze() override;
void calcSynthesize() override;
void showAnalyze() override;
void showSynthesize() override;
void show_results() override;
void syn_fun( double*, double*, double, double, double, double );
private:
MICROSTRIP* aux_ms;
COUPLED_MICROSTRIP m_calc;
};
#endif // _C_MICROSTRIP_H_

View File

@ -0,0 +1,118 @@
/*
* Copyright (C) 2002 Claudio Girardi <claudio.girardi@ieee.org>
* Copyright (C) 2005, 2006 Stefan Jahn <stefan@lkcc.org>
* Copyright The KiCad Developers, see AUTHORS.txt for contributors.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or (at
* your option) any later version.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this package; see the file COPYING. If not, write to
* the Free Software Foundation, Inc., 51 Franklin Street - Fifth Floor,
* Boston, MA 02110-1301, USA.
*/
#include "c_stripline.h"
#include "transline.h"
#include "units.h"
C_STRIPLINE::C_STRIPLINE()
{
m_Name = "Coupled_MicroStrip";
Init();
}
void C_STRIPLINE::calcAnalyze()
{
m_calc.Analyse();
}
void C_STRIPLINE::calcSynthesize()
{
m_calc.Synthesize( SYNTHESIZE_OPTS::DEFAULT );
}
void C_STRIPLINE::showAnalyze()
{
std::unordered_map<TRANSLINE_PARAMETERS, std::pair<double, TRANSLINE_STATUS>>& results =
m_calc.GetAnalysisResults();
setProperty( Z0_E_PRM, results[TRANSLINE_PARAMETERS::Z0_E].first );
setProperty( Z0_O_PRM, results[TRANSLINE_PARAMETERS::Z0_O].first );
setProperty( ANG_L_PRM, results[TRANSLINE_PARAMETERS::ANG_L].first );
setResult( 0, results[TRANSLINE_PARAMETERS::EPSILON_EFF_EVEN].first, "" );
setResult( 1, results[TRANSLINE_PARAMETERS::EPSILON_EFF_ODD].first, "" );
setResult( 2, results[TRANSLINE_PARAMETERS::UNIT_PROP_DELAY_EVEN].first, "ps/cm" );
setResult( 3, results[TRANSLINE_PARAMETERS::UNIT_PROP_DELAY_ODD].first, "ps/cm" );
setResult( 4, results[TRANSLINE_PARAMETERS::SKIN_DEPTH].first / UNIT_MICRON, "µm" );
setResult( 5, results[TRANSLINE_PARAMETERS::Z_DIFF].first, "Ω" );
setErrorLevel( Z0_E_PRM, convertParameterStatusCode( results[TRANSLINE_PARAMETERS::Z0_E].second ) );
setErrorLevel( Z0_O_PRM, convertParameterStatusCode( results[TRANSLINE_PARAMETERS::Z0_O].second ) );
setErrorLevel( ANG_L_PRM, convertParameterStatusCode( results[TRANSLINE_PARAMETERS::ANG_L].second ) );
setErrorLevel( PHYS_WIDTH_PRM, convertParameterStatusCode( results[TRANSLINE_PARAMETERS::PHYS_WIDTH].second ) );
setErrorLevel( PHYS_LEN_PRM, convertParameterStatusCode( results[TRANSLINE_PARAMETERS::PHYS_LEN].second ) );
setErrorLevel( PHYS_S_PRM, convertParameterStatusCode( results[TRANSLINE_PARAMETERS::PHYS_S].second ) );
}
void C_STRIPLINE::showSynthesize()
{
std::unordered_map<TRANSLINE_PARAMETERS, std::pair<double, TRANSLINE_STATUS>>& results =
m_calc.GetAnalysisResults();
setProperty( PHYS_WIDTH_PRM, results[TRANSLINE_PARAMETERS::PHYS_WIDTH].first );
setProperty( PHYS_S_PRM, results[TRANSLINE_PARAMETERS::PHYS_S].first );
setProperty( PHYS_LEN_PRM, results[TRANSLINE_PARAMETERS::PHYS_LEN].first );
setResult( 0, results[TRANSLINE_PARAMETERS::EPSILON_EFF_EVEN].first, "" );
setResult( 1, results[TRANSLINE_PARAMETERS::EPSILON_EFF_ODD].first, "" );
setResult( 2, results[TRANSLINE_PARAMETERS::UNIT_PROP_DELAY_EVEN].first, "ps/cm" );
setResult( 3, results[TRANSLINE_PARAMETERS::UNIT_PROP_DELAY_ODD].first, "ps/cm" );
setResult( 4, results[TRANSLINE_PARAMETERS::SKIN_DEPTH].first / UNIT_MICRON, "µm" );
setResult( 5, results[TRANSLINE_PARAMETERS::Z_DIFF].first, "Ω" );
setErrorLevel( Z0_E_PRM, convertParameterStatusCode( results[TRANSLINE_PARAMETERS::Z0_E].second ) );
setErrorLevel( Z0_O_PRM, convertParameterStatusCode( results[TRANSLINE_PARAMETERS::Z0_O].second ) );
setErrorLevel( ANG_L_PRM, convertParameterStatusCode( results[TRANSLINE_PARAMETERS::ANG_L].second ) );
setErrorLevel( PHYS_WIDTH_PRM, convertParameterStatusCode( results[TRANSLINE_PARAMETERS::PHYS_WIDTH].second ) );
setErrorLevel( PHYS_LEN_PRM, convertParameterStatusCode( results[TRANSLINE_PARAMETERS::PHYS_LEN].second ) );
setErrorLevel( PHYS_S_PRM, convertParameterStatusCode( results[TRANSLINE_PARAMETERS::PHYS_S].second ) );
}
void C_STRIPLINE::getProperties()
{
TRANSLINE::getProperties();
m_calc.SetParameter( TRANSLINE_PARAMETERS::Z0_E, m_parameters[Z0_E_PRM] );
m_calc.SetParameter( TRANSLINE_PARAMETERS::Z0_O, m_parameters[Z0_O_PRM] );
m_calc.SetParameter( TRANSLINE_PARAMETERS::EPSILONR, m_parameters[EPSILONR_PRM] );
m_calc.SetParameter( TRANSLINE_PARAMETERS::PHYS_WIDTH, m_parameters[PHYS_WIDTH_PRM] );
m_calc.SetParameter( TRANSLINE_PARAMETERS::PHYS_LEN, m_parameters[PHYS_LEN_PRM] );
m_calc.SetParameter( TRANSLINE_PARAMETERS::PHYS_S, m_parameters[PHYS_S_PRM] );
m_calc.SetParameter( TRANSLINE_PARAMETERS::H, m_parameters[H_PRM] );
m_calc.SetParameter( TRANSLINE_PARAMETERS::T, m_parameters[T_PRM] );
m_calc.SetParameter( TRANSLINE_PARAMETERS::FREQUENCY, m_parameters[FREQUENCY_PRM] );
m_calc.SetParameter( TRANSLINE_PARAMETERS::MURC, m_parameters[MURC_PRM] );
m_calc.SetParameter( TRANSLINE_PARAMETERS::SKIN_DEPTH, m_parameters[SKIN_DEPTH_PRM] );
m_calc.SetParameter( TRANSLINE_PARAMETERS::SIGMA, m_parameters[SIGMA_PRM] );
m_calc.SetParameter( TRANSLINE_PARAMETERS::ANG_L, m_parameters[ANG_L_PRM] );
}
void C_STRIPLINE::show_results()
{
}

View File

@ -0,0 +1,44 @@
/*
* Copyright The KiCad Developers, see AUTHORS.txt for contributors.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this package; see the file COPYING. If not, write to
* the Free Software Foundation, Inc., 51 Franklin Street - Fifth Floor,
* Boston, MA 02110-1301, USA.
*/
#ifndef C_STRIPLINE_H_
#define C_STRIPLINE_H_
#include "transline/transline.h"
#include <transline_calculations/coupled_stripline.h>
class C_STRIPLINE : public TRANSLINE
{
public:
C_STRIPLINE();
private:
void calcAnalyze() override;
void calcSynthesize() override;
void showAnalyze() override;
void showSynthesize() override;
void show_results() override;
void getProperties() override;
COUPLED_STRIPLINE m_calc;
};
#endif // C_STRIPLINE_H_

View File

@ -30,512 +30,100 @@
* Based on the original microstrip.c by Gopal Narayanan
*/
#include <cmath>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include "microstrip.h"
#include "transline.h"
#include "units.h"
MICROSTRIP::MICROSTRIP() : TRANSLINE(),
h( 0.0 ), // height of substrate
ht( 0.0 ), // height to the top of box
t( 0.0 ), // thickness of top metal
rough( 0.0 ), // Roughness of top metal
mur( 0.0 ), // magnetic permeability of substrate
w( 0.0 ), // width of line
l( 0.0 ), // length of line
Z0_0( 0.0 ), // static characteristic impedance
Z0( 0.0 ), // characteristic impedance
er_eff_0( 0.0 ), // Static effective dielectric constant
mur_eff( 0.0 ), // Effective mag. permeability
w_eff( 0.0 ), // Effective width of line
atten_dielectric( 0.0 ), // Loss in dielectric (dB)
atten_cond( 0.0 ), // Loss in conductors (dB)
Z0_h_1( 0.0 ) // homogeneous stripline impedance
MICROSTRIP_UI::MICROSTRIP_UI()
{
m_Name = "MicroStrip";
Init();
}
/*
* Z0_homogeneous() - compute the impedance for a stripline in a
* homogeneous medium, without cover effects
*/
double MICROSTRIP::Z0_homogeneous( double u )
void MICROSTRIP_UI::calcAnalyze()
{
double freq, Z0_value;
freq = 6.0 + ( 2.0 * M_PI - 6.0 ) * exp( -pow( 30.666 / u, 0.7528 ) );
Z0_value = ( ZF0 / ( 2.0 * M_PI ) ) * log( freq / u + sqrt( 1.0 + 4.0 / ( u * u ) ) );
return Z0_value;
m_calc.Analyse();
}
/*
* delta_Z0_cover() - compute the cover effect on impedance for a
* stripline in a homogeneous medium
*/
double MICROSTRIP::delta_Z0_cover( double u, double h2h )
void MICROSTRIP_UI::showAnalyze()
{
double P, Q;
double h2hp1;
std::unordered_map<TRANSLINE_PARAMETERS, std::pair<double, TRANSLINE_STATUS>>& results =
m_calc.GetAnalysisResults();
h2hp1 = 1.0 + h2h;
P = 270.0 * ( 1.0 - tanh( 1.192 + 0.706 * sqrt( h2hp1 ) - 1.389 / h2hp1 ) );
Q = 1.0109 - atanh( ( 0.012 * u + 0.177 * u * u - 0.027 * u * u * u ) / ( h2hp1 * h2hp1 ) );
return P * Q;
setProperty( Z0_PRM, results[TRANSLINE_PARAMETERS::Z0].first );
setProperty( ANG_L_PRM, results[TRANSLINE_PARAMETERS::ANG_L].first );
setResult( 0, results[TRANSLINE_PARAMETERS::EPSILON_EFF].first, "" );
setResult( 1, results[TRANSLINE_PARAMETERS::UNIT_PROP_DELAY].first, "ps/cm" );
setResult( 2, results[TRANSLINE_PARAMETERS::ATTEN_COND].first, "dB" );
setResult( 3, results[TRANSLINE_PARAMETERS::ATTEN_DILECTRIC].first, "dB" );
setResult( 4, results[TRANSLINE_PARAMETERS::SKIN_DEPTH].first / UNIT_MICRON, "µm" );
setErrorLevel( Z0_PRM, convertParameterStatusCode( results[TRANSLINE_PARAMETERS::Z0].second ) );
setErrorLevel( ANG_L_PRM, convertParameterStatusCode( results[TRANSLINE_PARAMETERS::ANG_L].second ) );
setErrorLevel( PHYS_LEN_PRM, convertParameterStatusCode( results[TRANSLINE_PARAMETERS::PHYS_LEN].second ) );
setErrorLevel( PHYS_WIDTH_PRM, convertParameterStatusCode( results[TRANSLINE_PARAMETERS::PHYS_WIDTH].second ) );
}
/*
* filling_factor() - compute the filling factor for a microstrip
* without cover and zero conductor thickness
*/
double MICROSTRIP::filling_factor( double u, double e_r )
void MICROSTRIP_UI::showSynthesize()
{
double a, b, q_inf;
double u2, u3, u4;
std::unordered_map<TRANSLINE_PARAMETERS, std::pair<double, TRANSLINE_STATUS>>& results =
m_calc.GetSynthesisResults();
u2 = u * u;
u3 = u2 * u;
u4 = u3 * u;
a = 1.0 + log( ( u4 + u2 / 2704 ) / ( u4 + 0.432 ) ) / 49.0 + log( 1.0 + u3 / 5929.741 ) / 18.7;
b = 0.564 * pow( ( e_r - 0.9 ) / ( e_r + 3.0 ), 0.053 );
q_inf = pow( 1.0 + 10.0 / u, -a * b );
return q_inf;
setProperty( PHYS_WIDTH_PRM, results[TRANSLINE_PARAMETERS::PHYS_WIDTH].first );
setProperty( PHYS_LEN_PRM, results[TRANSLINE_PARAMETERS::PHYS_LEN].first );
setProperty( Z0_PRM, results[TRANSLINE_PARAMETERS::Z0].first );
setProperty( ANG_L_PRM, results[TRANSLINE_PARAMETERS::ANG_L].first );
setResult( 0, results[TRANSLINE_PARAMETERS::EPSILON_EFF].first, "" );
setResult( 1, results[TRANSLINE_PARAMETERS::UNIT_PROP_DELAY].first, "ps/cm" );
setResult( 2, results[TRANSLINE_PARAMETERS::ATTEN_COND].first, "dB" );
setResult( 3, results[TRANSLINE_PARAMETERS::ATTEN_DILECTRIC].first, "dB" );
setResult( 4, results[TRANSLINE_PARAMETERS::SKIN_DEPTH].first / UNIT_MICRON, "µm" );
setErrorLevel( Z0_PRM, convertParameterStatusCode( results[TRANSLINE_PARAMETERS::Z0].second ) );
setErrorLevel( ANG_L_PRM, convertParameterStatusCode( results[TRANSLINE_PARAMETERS::ANG_L].second ) );
setErrorLevel( PHYS_LEN_PRM, convertParameterStatusCode( results[TRANSLINE_PARAMETERS::PHYS_LEN].second ) );
setErrorLevel( PHYS_WIDTH_PRM, convertParameterStatusCode( results[TRANSLINE_PARAMETERS::PHYS_WIDTH].second ) );
}
/*
* delta_q_cover() - compute the cover effect on filling factor
*/
double MICROSTRIP::delta_q_cover( double h2h )
void MICROSTRIP_UI::getProperties()
{
double q_c;
TRANSLINE::getProperties();
q_c = tanh( 1.043 + 0.121 * h2h - 1.164 / h2h );
return q_c;
m_calc.SetParameter( TRANSLINE_PARAMETERS::SIGMA, m_parameters[SIGMA_PRM] );
m_calc.SetParameter( TRANSLINE_PARAMETERS::EPSILON_EFF, m_parameters[EPSILON_EFF_PRM] );
m_calc.SetParameter( TRANSLINE_PARAMETERS::SKIN_DEPTH, m_parameters[SKIN_DEPTH_PRM] );
m_calc.SetParameter( TRANSLINE_PARAMETERS::EPSILONR, m_parameters[EPSILONR_PRM] );
m_calc.SetParameter( TRANSLINE_PARAMETERS::H_T, m_parameters[H_T_PRM] );
m_calc.SetParameter( TRANSLINE_PARAMETERS::H, m_parameters[H_PRM] );
m_calc.SetParameter( TRANSLINE_PARAMETERS::PHYS_WIDTH, m_parameters[PHYS_WIDTH_PRM] );
m_calc.SetParameter( TRANSLINE_PARAMETERS::T, m_parameters[T_PRM] );
m_calc.SetParameter( TRANSLINE_PARAMETERS::Z0, m_parameters[Z0_PRM] );
m_calc.SetParameter( TRANSLINE_PARAMETERS::FREQUENCY, m_parameters[FREQUENCY_PRM] );
m_calc.SetParameter( TRANSLINE_PARAMETERS::ROUGH, m_parameters[ROUGH_PRM] );
m_calc.SetParameter( TRANSLINE_PARAMETERS::TAND, m_parameters[TAND_PRM] );
m_calc.SetParameter( TRANSLINE_PARAMETERS::PHYS_LEN, m_parameters[PHYS_LEN_PRM] );
m_calc.SetParameter( TRANSLINE_PARAMETERS::MUR, m_parameters[MUR_PRM] );
m_calc.SetParameter( TRANSLINE_PARAMETERS::MURC, m_parameters[MURC_PRM] );
m_calc.SetParameter( TRANSLINE_PARAMETERS::ANG_L, m_parameters[ANG_L_PRM] );
}
/*
* delta_q_thickness() - compute the thickness effect on filling factor
*/
double MICROSTRIP::delta_q_thickness( double u, double t_h )
void MICROSTRIP_UI::show_results()
{
double q_t;
q_t = ( 2.0 * log( 2.0 ) / M_PI ) * ( t_h / sqrt( u ) );
return q_t;
}
/*
* e_r_effective() - compute effective dielectric constant from
* material e_r and filling factor
*/
double MICROSTRIP::e_r_effective( double e_r, double q )
{
double e_r_eff;
e_r_eff = 0.5 * ( e_r + 1.0 ) + 0.5 * q * ( e_r - 1.0 );
return e_r_eff;
}
/*
* delta_u_thickness - compute the thickness effect on normalized width
*/
double MICROSTRIP::delta_u_thickness( double u, double t_h, double e_r )
{
double delta_u;
if( t_h > 0.0 )
{
/* correction for thickness for a homogeneous microstrip */
delta_u = ( t_h / M_PI )
* log( 1.0 + ( 4.0 * M_E ) * pow( tanh( sqrt( 6.517 * u ) ), 2.0 ) / t_h );
/* correction for strip on a substrate with relative permettivity e_r */
delta_u = 0.5 * delta_u * ( 1.0 + 1.0 / cosh( sqrt( e_r - 1.0 ) ) );
}
else
{
delta_u = 0.0;
}
return delta_u;
}
/*
* microstrip_Z0() - compute microstrip static impedance
*/
void MICROSTRIP::microstrip_Z0()
{
double e_r, h2, h2h, u, t_h;
double Z0_h_r;
double delta_u_1, delta_u_r, q_inf, q_c, q_t, e_r_eff, e_r_eff_t, q;
e_r = m_parameters[EPSILONR_PRM];
h2 = m_parameters[H_T_PRM];
h2h = h2 / m_parameters[H_PRM];
u = m_parameters[PHYS_WIDTH_PRM] / m_parameters[H_PRM];
t_h = m_parameters[T_PRM] / m_parameters[H_PRM];
/* compute normalized width correction for e_r = 1.0 */
delta_u_1 = delta_u_thickness( u, t_h, 1.0 );
/* compute homogeneous stripline impedance */
Z0_h_1 = Z0_homogeneous( u + delta_u_1 );
/* compute normalized width correction */
delta_u_r = delta_u_thickness( u, t_h, e_r );
u += delta_u_r;
/* compute homogeneous stripline impedance */
Z0_h_r = Z0_homogeneous( u );
/* filling factor, with width corrected for thickness */
q_inf = filling_factor( u, e_r );
/* cover effect */
q_c = delta_q_cover( h2h );
/* thickness effect */
q_t = delta_q_thickness( u, t_h );
/* resultant filling factor */
q = ( q_inf - q_t ) * q_c;
/* e_r corrected for thickness and non homogeneous material */
e_r_eff_t = e_r_effective( e_r, q );
/* effective dielectric constant */
e_r_eff = e_r_eff_t * pow( Z0_h_1 / Z0_h_r, 2.0 );
/* characteristic impedance, corrected for thickness, cover */
/* and non homogeneous material */
m_parameters[Z0_PRM] = Z0_h_r / sqrt( e_r_eff_t );
w_eff = u * m_parameters[H_PRM];
er_eff_0 = e_r_eff;
Z0_0 = m_parameters[Z0_PRM];
}
/*
* e_r_dispersion() - computes the dispersion correction factor for
* the effective permeability
*/
double MICROSTRIP::e_r_dispersion( double u, double e_r, double f_n )
{
double P_1, P_2, P_3, P_4, P;
P_1 = 0.27488 + u * ( 0.6315 + 0.525 / pow( 1.0 + 0.0157 * f_n, 20.0 ) )
- 0.065683 * exp( -8.7513 * u );
P_2 = 0.33622 * ( 1.0 - exp( -0.03442 * e_r ) );
P_3 = 0.0363 * exp( -4.6 * u ) * ( 1.0 - exp( -pow( f_n / 38.7, 4.97 ) ) );
P_4 = 1.0 + 2.751 * ( 1.0 - exp( -pow( e_r / 15.916, 8.0 ) ) );
P = P_1 * P_2 * pow( ( P_3 * P_4 + 0.1844 ) * f_n, 1.5763 );
return P;
}
/*
* Z0_dispersion() - computes the dispersion correction factor for the
* characteristic impedance
*/
double MICROSTRIP::Z0_dispersion(
double u, double e_r, double e_r_eff_0, double e_r_eff_f, double f_n )
{
double R_1, R_2, R_3, R_4, R_5, R_6, R_7, R_8, R_9, R_10, R_11, R_12, R_13, R_14, R_15, R_16,
R_17, D, tmpf;
R_1 = 0.03891 * pow( e_r, 1.4 );
R_2 = 0.267 * pow( u, 7.0 );
R_3 = 4.766 * exp( -3.228 * pow( u, 0.641 ) );
R_4 = 0.016 + pow( 0.0514 * e_r, 4.524 );
R_5 = pow( f_n / 28.843, 12.0 );
R_6 = 22.2 * pow( u, 1.92 );
R_7 = 1.206 - 0.3144 * exp( -R_1 ) * ( 1.0 - exp( -R_2 ) );
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 ) ) );
tmpf = pow( e_r - 1.0, 6.0 );
R_9 = 5.086 * R_4 * ( R_5 / ( 0.3838 + 0.386 * R_4 ) )
* ( exp( -R_6 ) / ( 1.0 + 1.2992 * R_5 ) ) * ( tmpf / ( 1.0 + 10.0 * tmpf ) );
R_10 = 0.00044 * pow( e_r, 2.136 ) + 0.0184;
tmpf = pow( f_n / 19.47, 6.0 );
R_11 = tmpf / ( 1.0 + 0.0962 * tmpf );
R_12 = 1.0 / ( 1.0 + 0.00245 * u * u );
R_13 = 0.9408 * pow( e_r_eff_f, R_8 ) - 0.9603;
R_14 = ( 0.9408 - R_9 ) * pow( e_r_eff_0, R_8 ) - 0.9603;
R_15 = 0.707 * R_10 * pow( f_n / 12.3, 1.097 );
R_16 = 1.0 + 0.0503 * e_r * e_r * R_11 * ( 1.0 - exp( -pow( u / 15.0, 6.0 ) ) );
R_17 = R_7 * ( 1.0 - 1.1241 * ( R_12 / R_16 ) * exp( -0.026 * pow( f_n, 1.15656 ) - R_15 ) );
D = pow( R_13 / R_14, R_17 );
return D;
}
/*
* dispersion() - compute frequency dependent parameters of
* microstrip
*/
void MICROSTRIP::dispersion()
{
double e_r, e_r_eff_0;
double u, f_n, P, e_r_eff_f, D, Z0_f;
e_r = m_parameters[EPSILONR_PRM];
e_r_eff_0 = er_eff_0;
u = m_parameters[PHYS_WIDTH_PRM] / m_parameters[H_PRM];
/* normalized frequency [GHz * mm] */
f_n = m_parameters[FREQUENCY_PRM] * m_parameters[H_PRM] / 1e06;
P = e_r_dispersion( u, e_r, f_n );
/* effective dielectric constant corrected for dispersion */
e_r_eff_f = e_r - ( e_r - e_r_eff_0 ) / ( 1.0 + P );
D = Z0_dispersion( u, e_r, e_r_eff_0, e_r_eff_f, f_n );
Z0_f = Z0_0 * D;
// 1e10 factor is to convert from s/m to ps/cm
unit_prop_delay = calcUnitPropagationDelay( e_r_eff_f );
m_parameters[EPSILON_EFF_PRM] = e_r_eff_f;
m_parameters[Z0_PRM] = Z0_f;
}
/*
* conductor_losses() - compute microstrip conductor losses per unit
* length
*/
double MICROSTRIP::conductor_losses()
{
double e_r_eff_0, delta;
double K, R_s, Q_c, alpha_c;
e_r_eff_0 = er_eff_0;
delta = m_parameters[SKIN_DEPTH_PRM];
if( m_parameters[FREQUENCY_PRM] > 0.0 )
{
/* current distribution factor */
K = exp( -1.2 * pow( Z0_h_1 / ZF0, 0.7 ) );
/* skin resistance */
R_s = 1.0 / ( m_parameters[SIGMA_PRM] * delta );
/* correction for surface roughness */
R_s *= 1.0
+ ( ( 2.0 / M_PI )
* atan( 1.40 * pow( ( m_parameters[ROUGH_PRM] / delta ), 2.0 ) ) );
/* strip inductive quality factor */
Q_c = ( M_PI * Z0_h_1 * m_parameters[PHYS_WIDTH_PRM] * m_parameters[FREQUENCY_PRM] )
/ ( R_s * C0 * K );
alpha_c = ( 20.0 * M_PI / log( 10.0 ) ) * m_parameters[FREQUENCY_PRM] * sqrt( e_r_eff_0 )
/ ( C0 * Q_c );
}
else
{
alpha_c = 0.0;
}
return alpha_c;
}
/*
* dielectric_losses() - compute microstrip dielectric losses per unit
* length
*/
double MICROSTRIP::dielectric_losses()
{
double e_r, e_r_eff_0;
double alpha_d;
e_r = m_parameters[EPSILONR_PRM];
e_r_eff_0 = er_eff_0;
alpha_d = ( 20.0 * M_PI / log( 10.0 ) ) * ( m_parameters[FREQUENCY_PRM] / C0 )
* ( e_r / sqrt( e_r_eff_0 ) ) * ( ( e_r_eff_0 - 1.0 ) / ( e_r - 1.0 ) )
* m_parameters[TAND_PRM];
return alpha_d;
}
/*
* attenuation() - compute attenuation of microstrip
*/
void MICROSTRIP::attenuation()
{
m_parameters[SKIN_DEPTH_PRM] = skin_depth();
atten_cond = conductor_losses() * m_parameters[PHYS_LEN_PRM];
atten_dielectric = dielectric_losses() * m_parameters[PHYS_LEN_PRM];
}
/*
* mur_eff_ms() - returns effective magnetic permeability
*/
void MICROSTRIP::mur_eff_ms()
{
double* mur = &m_parameters[MUR_PRM];
double* h = &m_parameters[H_PRM];
double* w = &m_parameters[PHYS_WIDTH_PRM];
mur_eff = ( 2.0 * *mur )
/ ( ( 1.0 + *mur ) + ( ( 1.0 - *mur ) * pow( ( 1.0 + ( 10.0 * *h / *w ) ), -0.5 ) ) );
}
// synth_width - calculate width given Z0 and e_r
double MICROSTRIP::synth_width()
{
double e_r, a, b;
double w_h, width;
e_r = m_parameters[EPSILONR_PRM];
a = ( ( m_parameters[Z0_PRM] / ZF0 / 2 / M_PI ) * sqrt( ( e_r + 1 ) / 2. ) )
+ ( ( e_r - 1 ) / ( e_r + 1 ) * ( 0.23 + ( 0.11 / e_r ) ) );
b = ZF0 / 2 * M_PI / ( m_parameters[Z0_PRM] * sqrt( e_r ) );
if( a > 1.52 )
{
w_h = 8 * exp( a ) / ( exp( 2. * a ) - 2 );
}
else
{
w_h = ( 2. / M_PI )
* ( b - 1. - log( ( 2 * b ) - 1. )
+ ( ( e_r - 1 ) / ( 2 * e_r ) ) * ( log( b - 1. ) + 0.39 - 0.61 / e_r ) );
}
if( m_parameters[H_PRM] > 0.0 )
width = w_h * m_parameters[H_PRM];
else
width = 0;
return width;
}
/*
* line_angle() - calculate microstrip length in radians
*/
void MICROSTRIP::line_angle()
{
double e_r_eff;
double v, lambda_g;
e_r_eff = m_parameters[EPSILON_EFF_PRM];
/* velocity */
v = C0 / sqrt( e_r_eff * mur_eff );
/* wavelength */
lambda_g = v / m_parameters[FREQUENCY_PRM];
/* electrical angles */
m_parameters[ANG_L_PRM] = 2.0 * M_PI * m_parameters[PHYS_LEN_PRM] / lambda_g; /* in radians */
}
void MICROSTRIP::calcAnalyze()
{
/* effective permeability */
mur_eff_ms();
/* static impedance */
microstrip_Z0();
/* calculate freq dependence of er and Z0 */
dispersion();
/* calculate electrical lengths */
line_angle();
/* calculate losses */
attenuation();
}
void MICROSTRIP::show_results()
{
setProperty( Z0_PRM, m_parameters[Z0_PRM] );
setProperty( ANG_L_PRM, m_parameters[ANG_L_PRM] );
setResult( 0, m_parameters[EPSILON_EFF_PRM], "" );
setResult( 1, unit_prop_delay, "ps/cm" );
setResult( 2, atten_cond, "dB" );
setResult( 3, atten_dielectric, "dB" );
setResult( 4, m_parameters[SKIN_DEPTH_PRM] / UNIT_MICRON, "µm" );
}
void MICROSTRIP::showSynthesize()
{
setProperty( PHYS_WIDTH_PRM, m_parameters[PHYS_WIDTH_PRM] );
setProperty( PHYS_LEN_PRM, m_parameters[PHYS_LEN_PRM] );
// Check for errors
if( !std::isfinite( m_parameters[PHYS_LEN_PRM] ) || ( m_parameters[PHYS_LEN_PRM] < 0 ) )
setErrorLevel( PHYS_LEN_PRM, TRANSLINE_ERROR );
if( !std::isfinite( m_parameters[PHYS_WIDTH_PRM] ) || ( m_parameters[PHYS_WIDTH_PRM] <= 0 ) )
setErrorLevel( PHYS_WIDTH_PRM, TRANSLINE_ERROR );
// Check for warnings
if( !std::isfinite( m_parameters[Z0_PRM] ) || ( m_parameters[Z0_PRM] < 0 ) )
setErrorLevel( Z0_PRM, TRANSLINE_WARNING );
if( !std::isfinite( m_parameters[ANG_L_PRM] ) || ( m_parameters[ANG_L_PRM] < 0 ) )
setErrorLevel( ANG_L_PRM, TRANSLINE_WARNING );
}
void MICROSTRIP::showAnalyze()
{
setProperty( Z0_PRM, m_parameters[Z0_PRM] );
setProperty( ANG_L_PRM, m_parameters[ANG_L_PRM] );
// Check for errors
if( !std::isfinite( m_parameters[Z0_PRM] ) || ( m_parameters[Z0_PRM] < 0 ) )
setErrorLevel( Z0_PRM, TRANSLINE_ERROR );
if( !std::isfinite( m_parameters[ANG_L_PRM] ) || ( m_parameters[ANG_L_PRM] < 0 ) )
setErrorLevel( ANG_L_PRM, TRANSLINE_ERROR );
// Check for warnings
if( !std::isfinite( m_parameters[PHYS_LEN_PRM] ) || ( m_parameters[PHYS_LEN_PRM] < 0 ) )
setErrorLevel( PHYS_LEN_PRM, TRANSLINE_WARNING );
if( !std::isfinite( m_parameters[PHYS_WIDTH_PRM] ) || ( m_parameters[PHYS_WIDTH_PRM] <= 0 ) )
setErrorLevel( PHYS_WIDTH_PRM, TRANSLINE_WARNING );
}
/*
* synthesis function
*/
void MICROSTRIP::calcSynthesize()
void MICROSTRIP_UI::calcSynthesize()
{
double z0_dest = m_parameters[Z0_PRM];
double angl_dest = m_parameters[ANG_L_PRM];
/* calculate width and use for initial value in Newton's method */
m_parameters[PHYS_WIDTH_PRM] = synth_width();
minimizeZ0Error1D( &( m_parameters[PHYS_WIDTH_PRM] ) );
m_parameters[Z0_PRM] = z0_dest;
m_parameters[ANG_L_PRM] = angl_dest;
double const er_eff = m_parameters[EPSILON_EFF_PRM];
m_parameters[PHYS_LEN_PRM] = C0 / m_parameters[FREQUENCY_PRM] / sqrt( er_eff * mur_eff )
* m_parameters[ANG_L_PRM] / 2.0 / M_PI; /* in m */
calcAnalyze();
m_parameters[Z0_PRM] = z0_dest;
m_parameters[ANG_L_PRM] = angl_dest;
m_parameters[PHYS_LEN_PRM] = C0 / m_parameters[FREQUENCY_PRM] / sqrt( er_eff * mur_eff )
* m_parameters[ANG_L_PRM] / 2.0 / M_PI; /* in m */
m_calc.Synthesize( SYNTHESIZE_OPTS::DEFAULT );
}

View File

@ -4,6 +4,7 @@
* Copyright (C) 2001 Gopal Narayanan <gopal@astro.umass.edu>
* Copyright (C) 2005 Stefan Jahn <stefan@lkcc.org>
* Modified for Kicad: 2015 jean-pierre.charras
* Copyright The KiCad Developers, see AUTHORS.txt for contributors.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
@ -21,69 +22,30 @@
* Boston, MA 02110-1301, USA.
*/
#ifndef __MICROSTRIP_H
#define __MICROSTRIP_H
#include "transline/transline.h"
class MICROSTRIP : public TRANSLINE
#include "transline/transline.h"
#include <transline_calculations/microstrip.h>
class MICROSTRIP_UI : public TRANSLINE
{
public:
MICROSTRIP();
MICROSTRIP_UI();
friend class C_MICROSTRIP;
private:
double h; // height of substrate
double ht; // height to the top of box
double t; // thickness of top metal
double rough; // Roughness of top metal
double mur; // magnetic permeability of substrate
double w; // width of line
double l; // length of line
double Z0_0; // static characteristic impedance
double Z0; // characteristic impedance
double er_eff_0; // Static effective dielectric constant
double mur_eff; // Effective mag. permeability
double w_eff; // Effective width of line
double atten_dielectric; // Loss in dielectric (dB)
double atten_cond; // Loss in conductors (dB)
double unit_prop_delay; // Unit propagation delay (ps/cm)
MICROSTRIP m_calc;
// private params
double Z0_h_1; // homogeneous stripline impedance
private:
double er_eff_freq();
double alpha_c();
double alpha_c_roughness();
double alpha_dielectric();
double char_impedance_ht();
double synth_width();
double ereff_dispersion();
double Z0_dispersion();
double Z0_homogeneous( double );
double delta_Z0_cover( double, double );
double filling_factor( double, double );
double delta_q_cover( double );
double delta_q_thickness( double, double );
double e_r_effective( double, double );
double delta_u_thickness( double, double, double );
double e_r_dispersion( double, double, double );
double Z0_dispersion( double, double, double, double, double );
double conductor_losses();
double dielectric_losses();
void microstrip_Z0();
void dispersion();
void attenuation();
void mur_eff_ms();
void line_angle();
void show_results() override;
void showSynthesize() override;
void showAnalyze() override;
void calcAnalyze() override;
void calcSynthesize() override;
void getProperties() override;
void show_results() override;
void showSynthesize() override;
void showAnalyze() override;
void calcAnalyze() override;
void calcSynthesize() override;
};
#endif // __MICROSTRIP_H

View File

@ -3,6 +3,7 @@
*
* Copyright (C) 2011 Michael Margraf <michael.margraf@alumni.tu-berlin.de>
* Modifications 2018 for Kicad: Jean-Pierre Charras
* Copyright The KiCad Developers, see AUTHORS.txt for contributors.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@ -21,162 +22,97 @@
*
*/
#include <cmath>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include "stripline.h"
#include "units.h"
#include <units_scales.h>
STRIPLINE::STRIPLINE() : TRANSLINE(), unit_prop_delay( 0.0 )
STRIPLINE_UI::STRIPLINE_UI()
{
m_Name = "StripLine";
Init();
}
// -------------------------------------------------------------------
// calculate characteristic impedance and conductor loss (in db/meter)
double STRIPLINE::lineImpedance( double height, double& ac )
void STRIPLINE_UI::calcAnalyze()
{
double ZL;
double hmt = height - m_parameters[T_PRM];
ac = sqrt( m_parameters[FREQUENCY_PRM] / m_parameters[SIGMA_PRM] / 17.2 );
if( m_parameters[PHYS_WIDTH_PRM] / hmt >= 0.35 )
{
ZL = m_parameters[PHYS_WIDTH_PRM]
+ ( 2.0 * height * log( ( 2.0 * height - m_parameters[T_PRM] ) / hmt )
- m_parameters[T_PRM] * log( height * height / hmt / hmt - 1.0 ) )
/ M_PI;
ZL = ZF0 * hmt / sqrt( m_parameters[EPSILONR_PRM] ) / 4.0 / ZL;
ac *= 2.02e-6 * m_parameters[EPSILONR_PRM] * ZL / hmt;
ac *= 1.0 + 2.0 * m_parameters[PHYS_WIDTH_PRM] / hmt
+ ( height + m_parameters[T_PRM] ) / hmt / M_PI
* log( 2.0 * height / m_parameters[T_PRM] - 1.0 );
}
else
{
double tdw = m_parameters[T_PRM] / m_parameters[PHYS_WIDTH_PRM];
if( m_parameters[T_PRM] / m_parameters[PHYS_WIDTH_PRM] > 1.0 )
tdw = m_parameters[PHYS_WIDTH_PRM] / m_parameters[T_PRM];
double de = 1.0 + tdw / M_PI * ( 1.0 + log( 4.0 * M_PI / tdw ) ) + 0.236 * pow( tdw, 1.65 );
if( m_parameters[T_PRM] / m_parameters[PHYS_WIDTH_PRM] > 1.0 )
de *= m_parameters[T_PRM] / 2.0;
else
de *= m_parameters[PHYS_WIDTH_PRM] / 2.0;
ZL = ZF0 / 2.0 / M_PI / sqrt( m_parameters[EPSILONR_PRM] )
* log( 4.0 * height / M_PI / de );
ac *= 0.01141 / ZL / de;
ac *= de / height + 0.5 + tdw / 2.0 / M_PI + 0.5 / M_PI * log( 4.0 * M_PI / tdw )
+ 0.1947 * pow( tdw, 0.65 ) - 0.0767 * pow( tdw, 1.65 );
}
return ZL;
m_calc.Analyse();
}
// -------------------------------------------------------------------
void STRIPLINE::calcAnalyze()
void STRIPLINE_UI::calcSynthesize()
{
m_parameters[SKIN_DEPTH_PRM] = skin_depth();
m_parameters[EPSILON_EFF_PRM] = m_parameters[EPSILONR_PRM]; // no dispersion
double ac1, ac2;
double t = m_parameters[T_PRM];
double a = m_parameters[STRIPLINE_A_PRM];
double h = m_parameters[H_PRM];
m_parameters[Z0_PRM] = 2.0
/ ( 1.0 / lineImpedance( 2.0 * a + t, ac1 )
+ 1.0 / lineImpedance( 2.0 * ( h - a ) - t, ac2 ) );
m_parameters[LOSS_CONDUCTOR_PRM] = m_parameters[PHYS_LEN_PRM] * ( ac1 + ac2 );
m_parameters[LOSS_DIELECTRIC_PRM] = LOG2DB * m_parameters[PHYS_LEN_PRM]
* ( M_PI / C0 ) * m_parameters[FREQUENCY_PRM]
* sqrt( m_parameters[EPSILONR_PRM] )
* m_parameters[TAND_PRM];
m_parameters[ANG_L_PRM] = 2.0 * M_PI * m_parameters[PHYS_LEN_PRM]
* sqrt( m_parameters[EPSILONR_PRM] ) * m_parameters[FREQUENCY_PRM]
/ C0; // in radians
unit_prop_delay = calcUnitPropagationDelay( m_parameters[EPSILON_EFF_PRM] );
m_calc.Synthesize( SYNTHESIZE_OPTS::DEFAULT );
}
void STRIPLINE::showAnalyze()
void STRIPLINE_UI::showAnalyze()
{
setProperty( Z0_PRM, m_parameters[Z0_PRM] );
setProperty( ANG_L_PRM, m_parameters[ANG_L_PRM] );
std::unordered_map<TRANSLINE_PARAMETERS, std::pair<double, TRANSLINE_STATUS>>& results =
m_calc.GetAnalysisResults();
if( !std::isfinite( m_parameters[Z0_PRM] ) || m_parameters[Z0_PRM] < 0 )
setErrorLevel( Z0_PRM, TRANSLINE_ERROR );
setResult( 0, results[TRANSLINE_PARAMETERS::EPSILON_EFF].first, "" );
setResult( 1, results[TRANSLINE_PARAMETERS::UNIT_PROP_DELAY].first, "ps/cm" );
setResult( 2, results[TRANSLINE_PARAMETERS::LOSS_CONDUCTOR].first, "dB" );
setResult( 3, results[TRANSLINE_PARAMETERS::LOSS_DIELECTRIC].first, "dB" );
setResult( 4, results[TRANSLINE_PARAMETERS::SKIN_DEPTH].first / UNIT_MICRON, "µm" );
if( !std::isfinite( m_parameters[ANG_L_PRM] ) || m_parameters[ANG_L_PRM] < 0 )
setErrorLevel( ANG_L_PRM, TRANSLINE_ERROR );
setProperty( Z0_PRM, results[TRANSLINE_PARAMETERS::Z0].first );
setProperty( ANG_L_PRM, results[TRANSLINE_PARAMETERS::ANG_L].first );
if( !std::isfinite( m_parameters[PHYS_LEN_PRM] ) || m_parameters[PHYS_LEN_PRM] < 0 )
setErrorLevel( PHYS_LEN_PRM, TRANSLINE_WARNING );
if( !std::isfinite( m_parameters[PHYS_WIDTH_PRM] ) || m_parameters[PHYS_WIDTH_PRM] < 0 )
setErrorLevel( PHYS_WIDTH_PRM, TRANSLINE_WARNING );
if( m_parameters[STRIPLINE_A_PRM] + m_parameters[T_PRM] >= m_parameters[H_PRM] )
{
setErrorLevel( STRIPLINE_A_PRM, TRANSLINE_WARNING );
setErrorLevel( T_PRM, TRANSLINE_WARNING );
setErrorLevel( H_PRM, TRANSLINE_WARNING );
setErrorLevel( Z0_PRM, TRANSLINE_ERROR );
}
}
void STRIPLINE::showSynthesize()
{
setProperty( PHYS_LEN_PRM, m_parameters[PHYS_LEN_PRM] );
setProperty( PHYS_WIDTH_PRM, m_parameters[PHYS_WIDTH_PRM] );
if( !std::isfinite( m_parameters[PHYS_LEN_PRM] ) || m_parameters[PHYS_LEN_PRM] < 0 )
setErrorLevel( PHYS_LEN_PRM, TRANSLINE_ERROR );
if( !std::isfinite( m_parameters[PHYS_WIDTH_PRM] ) || m_parameters[PHYS_WIDTH_PRM] < 0 )
setErrorLevel( PHYS_WIDTH_PRM, TRANSLINE_ERROR );
if( !std::isfinite( m_parameters[Z0_PRM] ) || m_parameters[Z0_PRM] < 0 )
setErrorLevel( Z0_PRM, TRANSLINE_WARNING );
if( !std::isfinite( m_parameters[ANG_L_PRM] ) || m_parameters[ANG_L_PRM] < 0 )
setErrorLevel( ANG_L_PRM, TRANSLINE_WARNING );
if( m_parameters[STRIPLINE_A_PRM] + m_parameters[T_PRM] >= m_parameters[H_PRM] )
{
setErrorLevel( STRIPLINE_A_PRM, TRANSLINE_WARNING );
setErrorLevel( T_PRM, TRANSLINE_WARNING );
setErrorLevel( H_PRM, TRANSLINE_WARNING );
setErrorLevel( PHYS_WIDTH_PRM, TRANSLINE_ERROR );
}
}
// -------------------------------------------------------------------
void STRIPLINE::show_results()
{
setResult( 0, m_parameters[EPSILON_EFF_PRM], "" );
setResult( 1, unit_prop_delay, "ps/cm" );
setResult( 2, m_parameters[LOSS_CONDUCTOR_PRM], "dB" );
setResult( 3, m_parameters[LOSS_DIELECTRIC_PRM], "dB" );
setResult( 4, m_parameters[SKIN_DEPTH_PRM] / UNIT_MICRON, "µm" );
setErrorLevel( Z0_PRM, convertParameterStatusCode( results[TRANSLINE_PARAMETERS::Z0].second ) );
setErrorLevel( ANG_L_PRM, convertParameterStatusCode( results[TRANSLINE_PARAMETERS::ANG_L].second ) );
setErrorLevel( PHYS_LEN_PRM, convertParameterStatusCode( results[TRANSLINE_PARAMETERS::PHYS_LEN].second ) );
setErrorLevel( PHYS_WIDTH_PRM, convertParameterStatusCode( results[TRANSLINE_PARAMETERS::PHYS_WIDTH].second ) );
setErrorLevel( STRIPLINE_A_PRM, convertParameterStatusCode( results[TRANSLINE_PARAMETERS::STRIPLINE_A].second ) );
setErrorLevel( T_PRM, convertParameterStatusCode( results[TRANSLINE_PARAMETERS::T].second ) );
setErrorLevel( H_PRM, convertParameterStatusCode( results[TRANSLINE_PARAMETERS::T].second ) );
}
#define MAX_ERROR 0.000001
// -------------------------------------------------------------------
void STRIPLINE::calcSynthesize()
void STRIPLINE_UI::showSynthesize()
{
minimizeZ0Error1D( &( m_parameters[PHYS_WIDTH_PRM] ) );
std::unordered_map<TRANSLINE_PARAMETERS, std::pair<double, TRANSLINE_STATUS>>& results =
m_calc.GetSynthesisResults();
setResult( 0, results[TRANSLINE_PARAMETERS::EPSILON_EFF].first, "" );
setResult( 1, results[TRANSLINE_PARAMETERS::UNIT_PROP_DELAY].first, "ps/cm" );
setResult( 2, results[TRANSLINE_PARAMETERS::LOSS_CONDUCTOR].first, "dB" );
setResult( 3, results[TRANSLINE_PARAMETERS::LOSS_DIELECTRIC].first, "dB" );
setResult( 4, results[TRANSLINE_PARAMETERS::SKIN_DEPTH].first / UNIT_MICRON, "µm" );
setProperty( PHYS_LEN_PRM, results[TRANSLINE_PARAMETERS::PHYS_LEN].first );
setProperty( PHYS_WIDTH_PRM, results[TRANSLINE_PARAMETERS::PHYS_WIDTH].first );
setErrorLevel( Z0_PRM, convertParameterStatusCode( results[TRANSLINE_PARAMETERS::Z0].second ) );
setErrorLevel( ANG_L_PRM, convertParameterStatusCode( results[TRANSLINE_PARAMETERS::ANG_L].second ) );
setErrorLevel( PHYS_LEN_PRM, convertParameterStatusCode( results[TRANSLINE_PARAMETERS::PHYS_LEN].second ) );
setErrorLevel( PHYS_WIDTH_PRM, convertParameterStatusCode( results[TRANSLINE_PARAMETERS::PHYS_WIDTH].second ) );
setErrorLevel( STRIPLINE_A_PRM, convertParameterStatusCode( results[TRANSLINE_PARAMETERS::STRIPLINE_A].second ) );
setErrorLevel( T_PRM, convertParameterStatusCode( results[TRANSLINE_PARAMETERS::T].second ) );
setErrorLevel( H_PRM, convertParameterStatusCode( results[TRANSLINE_PARAMETERS::T].second ) );
}
void STRIPLINE_UI::show_results()
{
}
void STRIPLINE_UI::getProperties()
{
TRANSLINE::getProperties();
m_calc.SetParameter( TRANSLINE_PARAMETERS::SKIN_DEPTH, m_parameters[SKIN_DEPTH_PRM] );
m_calc.SetParameter( TRANSLINE_PARAMETERS::EPSILONR, m_parameters[EPSILONR_PRM] );
m_calc.SetParameter( TRANSLINE_PARAMETERS::T, m_parameters[T_PRM] );
m_calc.SetParameter( TRANSLINE_PARAMETERS::STRIPLINE_A, m_parameters[STRIPLINE_A_PRM] );
m_calc.SetParameter( TRANSLINE_PARAMETERS::H, m_parameters[H_PRM] );
m_calc.SetParameter( TRANSLINE_PARAMETERS::Z0, m_parameters[Z0_PRM] );
m_calc.SetParameter( TRANSLINE_PARAMETERS::PHYS_LEN, m_parameters[PHYS_LEN_PRM] );
m_calc.SetParameter( TRANSLINE_PARAMETERS::FREQUENCY, m_parameters[FREQUENCY_PRM] );
m_calc.SetParameter( TRANSLINE_PARAMETERS::TAND, m_parameters[TAND_PRM] );
m_calc.SetParameter( TRANSLINE_PARAMETERS::PHYS_WIDTH, m_parameters[PHYS_WIDTH_PRM] );
m_calc.SetParameter( TRANSLINE_PARAMETERS::ANG_L, m_parameters[ANG_L_PRM] );
m_calc.SetParameter( TRANSLINE_PARAMETERS::SIGMA, m_parameters[SIGMA_PRM] );
m_calc.SetParameter( TRANSLINE_PARAMETERS::MURC, m_parameters[MURC_PRM] );
}

View File

@ -3,6 +3,7 @@
*
* Copyright (C) 2011 Michael Margraf <michael.margraf@alumni.tu-berlin.de>
* Modifications 2011 for Kicad: Jean-Pierre Charras
* Copyright The KiCad Developers, see AUTHORS.txt for contributors.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
@ -21,26 +22,27 @@
*
*/
#ifndef __STRIPLINE_H
#define __STRIPLINE_H
#ifndef STRIPLINE_UI_H
#define STRIPLINE_UI_H
#include "transline/transline.h"
#include <transline_calculations/stripline.h>
class STRIPLINE : public TRANSLINE
class STRIPLINE_UI : public TRANSLINE
{
public:
STRIPLINE();
STRIPLINE_UI();
private:
void calcAnalyze() override;
void calcSynthesize() override;
void showSynthesize() override;
void showAnalyze() override;
double lineImpedance( double, double& );
void show_results() override;
void calcAnalyze() override;
void calcSynthesize() override;
void showSynthesize() override;
void showAnalyze() override;
void show_results() override;
void getProperties() override;
double unit_prop_delay;
STRIPLINE m_calc;
};
#endif
#endif //STRIPLINE_UI_H

View File

@ -443,4 +443,17 @@ void TRANSLINE::setErrorLevel( PRMS_ID aP, char aErrorLevel )
double TRANSLINE::calcUnitPropagationDelay( const double epsilonEff )
{
return std::sqrt( epsilonEff ) * ( 1.0e10 / 2.99e8 );
}
}
char TRANSLINE::convertParameterStatusCode( TRANSLINE_STATUS aStatus )
{
switch( aStatus )
{
case TRANSLINE_STATUS::OK: return TRANSLINE_OK;
case TRANSLINE_STATUS::WARNING: return TRANSLINE_WARNING;
case TRANSLINE_STATUS::ERROR: return TRANSLINE_ERROR;
}
return TRANSLINE_OK;
}

View File

@ -3,6 +3,7 @@
*
* Copyright (C) 2005 Stefan Jahn <stefan@lkcc.org>
* Modifications 2018 for Kicad: Jean-Pierre Charras
* Copyright The KiCad Developers, see AUTHORS.txt for contributors.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
@ -25,6 +26,7 @@
#define __TRANSLINE_H
#include <gal/color4d.h>
#include <transline_calculations/transline_calculation_base.h>
#define TRANSLINE_OK 0
#define TRANSLINE_WARNING 1
@ -86,7 +88,7 @@ public:
double getProperty( enum PRMS_ID aPrmId );
void getProperties();
virtual void getProperties();
void checkProperties();
void setResult( int, double, const char* );
void setResult( int, const char* );
@ -138,6 +140,9 @@ protected:
/// Calculates the unit propagation delay (in ps/cm) for the given effective dielectric constant
static double calcUnitPropagationDelay( double epsilonEff );
/// Converts a TRANSLINE_PARAMETER status to a PCB Calculation status
static char convertParameterStatusCode( TRANSLINE_STATUS aStatus );
};
#endif /* __TRANSLINE_H */

View File

@ -106,7 +106,7 @@ void PANEL_TRANSLINE::TranslineTypeSelection( enum TRANSLINE_TYPE_ID aType )
m_translineBitmap->SetBitmap( KiBitmapBundle( m_transline_list[m_currTransLineType]->m_BitmapName ) );
// This helper bitmap is shown for coupled microstrip only:
m_bmCMicrostripZoddZeven->Show( aType == C_MICROSTRIP_TYPE );
m_bmCMicrostripZoddZeven->Show( aType == C_MICROSTRIP_TYPE || aType == C_STRIPLINE_TYPE );
m_bmCMicrostripZoddZeven->SetBitmap( KiBitmapBundle( BITMAPS::microstrip_zodd_zeven ) );
TRANSLINE_IDENT* tr_ident = m_transline_list[m_currTransLineType];

View File

@ -36,6 +36,7 @@
#include "transline/c_microstrip.h"
#include "transline/stripline.h"
#include "transline/twistedpair.h"
#include "transline/c_stripline.h"
#include "pcb_calculator_settings.h"
#include "widgets/unit_selector.h"
@ -113,7 +114,7 @@ TRANSLINE_IDENT::TRANSLINE_IDENT( enum TRANSLINE_TYPE_ID aType )
switch( m_Type )
{
case MICROSTRIP_TYPE: // microstrip
m_TLine = new MICROSTRIP();
m_TLine = new MICROSTRIP_UI();
m_BitmapName = BITMAPS::microstrip;
m_Messages.Add( wxString::Format( _( "Effective %s:" ), wxT( "εr" ) ) );
@ -336,6 +337,37 @@ TRANSLINE_IDENT::TRANSLINE_IDENT( enum TRANSLINE_TYPE_ID aType )
AddPrm( new TRANSLINE_PRM( PRM_TYPE_PHYS, PHYS_LEN_PRM,
"L", "L", _( "Line length" ), 50.0, true ) );
AddPrm( new TRANSLINE_PRM( PRM_TYPE_ELEC, Z0_E_PRM, "Zeven", _( "Zeven" ),
_( "Even mode impedance (lines driven by common voltages)" ), 50.0, true ) );
AddPrm( new TRANSLINE_PRM( PRM_TYPE_ELEC, Z0_O_PRM, "Zodd", _( "Zodd" ),
_( "Odd mode impedance (lines driven by opposite "
"(differential) voltages)" ),
50.0, true ) );
AddPrm( new TRANSLINE_PRM( PRM_TYPE_ELEC, ANG_L_PRM, "Ang_l", "Ang_l", _( "Electrical length" ), 0.0, true ) );
break;
case C_STRIPLINE_TYPE: // Coupled stripline
m_TLine = new C_STRIPLINE();
m_BitmapName = BITMAPS::coupled_stripline;
m_HasPrmSelection = true;
m_Messages.Add( wxString::Format( _( "Effective %s (even):" ), wxT( "εr" ) ) );
m_Messages.Add( wxString::Format( _( "Effective %s (odd):" ), wxT( "εr" ) ) );
m_Messages.Add( _( "Unit propagation delay (even):" ) );
m_Messages.Add( _( "Unit propagation delay (odd):" ) );
m_Messages.Add( _( "Skin depth:" ) );
m_Messages.Add( _( "Differential Impedance (Zd):" ) );
AddPrm( new TRANSLINE_PRM( PRM_TYPE_SUBS, H_PRM, "H", "H", _( "Height of substrate" ), 0.2, true ) );
AddPrm( new TRANSLINE_PRM( PRM_TYPE_SUBS, T_PRM, "T", "T", _( "Strip thickness" ), 0.035, true ) );
AddPrm( new TRANSLINE_PRM( PRM_TYPE_SUBS, MURC_PRM, "mu rel C",
wxString::Format( wxT( "μ(%s)" ), _( "conductor" ) ),
_( "Relative permeability (mu) of conductor" ), 1, false ) );
AddPrm( new TRANSLINE_PRM( PRM_TYPE_PHYS, PHYS_WIDTH_PRM, "W", "W", _( "Line width" ), 0.2, true ) );
AddPrm( new TRANSLINE_PRM( PRM_TYPE_PHYS, PHYS_S_PRM, "S", "S", _( "Gap width" ), 0.2, true ) );
AddPrm( new TRANSLINE_PRM( PRM_TYPE_PHYS, PHYS_LEN_PRM, "L", "L", _( "Line length" ), 50.0, true ) );
AddPrm( new TRANSLINE_PRM( PRM_TYPE_ELEC, Z0_E_PRM,
"Zeven", _( "Zeven" ),
_( "Even mode impedance (lines driven by common voltages)" ),
@ -350,7 +382,7 @@ TRANSLINE_IDENT::TRANSLINE_IDENT( enum TRANSLINE_TYPE_ID aType )
break;
case STRIPLINE_TYPE: // stripline
m_TLine = new STRIPLINE();
m_TLine = new STRIPLINE_UI();
m_BitmapName = BITMAPS::stripline;
m_Messages.Add( wxString::Format( _( "Effective %s:" ), wxT( "εr" ) ) );

View File

@ -33,16 +33,18 @@
enum class BITMAPS : unsigned int;
// An enum to handle muwave shapes:
enum TRANSLINE_TYPE_ID {
enum TRANSLINE_TYPE_ID
{
START_OF_LIST_TYPE = 0,
DEFAULT_TYPE = START_OF_LIST_TYPE,
MICROSTRIP_TYPE = DEFAULT_TYPE,
C_MICROSTRIP_TYPE,
STRIPLINE_TYPE,
C_STRIPLINE_TYPE,
CPW_TYPE,
GROUNDED_CPW_TYPE,
RECTWAVEGUIDE_TYPE,
COAX_TYPE,
C_MICROSTRIP_TYPE,
STRIPLINE_TYPE,
TWISTEDPAIR_TYPE,
END_OF_LIST_TYPE
};

View File

@ -720,6 +720,7 @@ set( BMAPS_OTHER
color_code_tolerance
color_code_value
color_code_value_and_name
coupled_stripline
creepage_clearance
cpw
cpw_back

Binary file not shown.

After

Width:  |  Height:  |  Size: 9.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 9.9 KiB

View File

@ -0,0 +1,834 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<svg
width="85mm"
height="44mm"
viewBox="0 0 85 44"
version="1.1"
id="svg19844"
inkscape:version="1.4 (e7c3feb1, 2024-10-09)"
sodipodi:docname="coupled_stripline.svg"
inkscape:export-filename="/Users/jeff/kicad_dev/kicad/bitmaps_png/png_other/stripline.png"
inkscape:export-xdpi="96"
inkscape:export-ydpi="96"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns="http://www.w3.org/2000/svg"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#">
<defs
id="defs19838">
<marker
inkscape:stockid="TriangleInL"
orient="auto"
refY="0"
refX="0"
id="TriangleInL"
style="overflow:visible"
inkscape:isstock="true">
<path
id="path12142"
d="M 5.77,0 -2.88,5 V -5 Z"
style="fill:#0081d5;fill-opacity:1;fill-rule:evenodd;stroke:#0081d5;stroke-width:1pt;stroke-opacity:1"
transform="scale(-0.8)" />
</marker>
<marker
inkscape:stockid="Arrow2Lstart"
orient="auto"
refY="0"
refX="0"
id="Arrow2Lstart"
style="overflow:visible"
inkscape:isstock="true">
<path
id="path12027"
style="fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:0.625;stroke-linejoin:round;stroke-opacity:1"
d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z"
transform="matrix(1.1,0,0,1.1,1.1,0)" />
</marker>
<marker
inkscape:isstock="true"
style="overflow:visible"
id="marker23801"
refX="0"
refY="0"
orient="auto"
inkscape:stockid="TriangleOutL">
<path
transform="scale(0.8)"
style="fill:#0081d5;fill-opacity:1;fill-rule:evenodd;stroke:#0081d5;stroke-width:1pt;stroke-opacity:1"
d="M 5.77,0 -2.88,5 V -5 Z"
id="path23799" />
</marker>
<marker
inkscape:stockid="TriangleOutL"
orient="auto"
refY="0"
refX="0"
id="TriangleOutL"
style="overflow:visible"
inkscape:isstock="true"
inkscape:collect="always">
<path
id="path12151"
d="M 5.77,0 -2.88,5 V -5 Z"
style="fill:#0081d5;fill-opacity:1;fill-rule:evenodd;stroke:#0081d5;stroke-width:1pt;stroke-opacity:1"
transform="scale(0.8)" />
</marker>
<marker
style="overflow:visible"
id="DistanceEnd"
refX="0"
refY="0"
orient="auto"
inkscape:stockid="DistanceEnd"
inkscape:isstock="true">
<g
id="g2301"
style="fill:#0081d5;fill-opacity:1;stroke:#0081d5;stroke-opacity:1">
<path
style="fill:#0081d5;fill-opacity:1;stroke:#0081d5;stroke-width:1.15;stroke-linecap:square;stroke-opacity:1"
d="M 0,0 H -2"
id="path2316" />
<path
style="fill:#0081d5;fill-opacity:1;fill-rule:evenodd;stroke:#0081d5;stroke-opacity:1"
d="m 0,0 -13,4 4,-4 -4,-4 z"
id="path2312" />
<path
style="fill:#0081d5;fill-opacity:1;stroke:#0081d5;stroke-width:1;stroke-linecap:square;stroke-opacity:1"
d="M 0,-4 V 40"
id="path2314" />
</g>
</marker>
<marker
style="overflow:visible"
id="DistanceStart"
refX="0"
refY="0"
orient="auto"
inkscape:stockid="DistanceStart"
inkscape:isstock="true">
<g
id="g2300"
style="fill:#0081d5;fill-opacity:1;stroke:#0081d5;stroke-opacity:1">
<path
style="fill:#0081d5;fill-opacity:1;stroke:#0081d5;stroke-width:1.15;stroke-linecap:square;stroke-opacity:1"
d="M 0,0 H 2"
id="path2306" />
<path
style="fill:#0081d5;fill-opacity:1;fill-rule:evenodd;stroke:#0081d5;stroke-opacity:1"
d="M 0,0 13,4 9,0 13,-4 Z"
id="path2302" />
<path
style="fill:#0081d5;fill-opacity:1;stroke:#0081d5;stroke-width:1;stroke-linecap:square;stroke-opacity:1"
d="M 0,-4 V 40"
id="path2304" />
</g>
</marker>
<marker
inkscape:stockid="Arrow2Lend"
orient="auto"
refY="0"
refX="0"
id="marker21133"
style="overflow:visible"
inkscape:isstock="true">
<path
id="path21131"
style="fill:#0081d5;fill-opacity:1;fill-rule:evenodd;stroke:#0081d5;stroke-width:0.625;stroke-linejoin:round;stroke-opacity:1"
d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z"
transform="matrix(-1.1,0,0,-1.1,-1.1,0)" />
</marker>
<marker
inkscape:stockid="RazorWire"
id="RazorWire"
refX="0"
refY="0"
orient="auto"
style="overflow:visible"
inkscape:isstock="true">
<path
id="path12241"
transform="scale(0.8)"
style="fill:#0081d5;fill-opacity:1;fill-rule:evenodd;stroke:#0081d5;stroke-width:0.1pt;stroke-opacity:1"
d="m 0.02272727,-0.74009011 v 1.4375 L -7.7585227,3.0099099 H 10.678977 L 3.4914773,0.69740989 v -1.4375 L 10.741477,-2.8963401 H -7.7272727 Z" />
</marker>
<marker
inkscape:stockid="Arrow2Lend"
orient="auto"
refY="0"
refX="0"
id="Arrow2Lend"
style="overflow:visible"
inkscape:isstock="true">
<path
id="path12030"
style="fill:#0081d5;fill-opacity:1;fill-rule:evenodd;stroke:#0081d5;stroke-width:0.625;stroke-linejoin:round;stroke-opacity:1"
d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z"
transform="matrix(-1.1,0,0,-1.1,-1.1,0)" />
</marker>
<marker
inkscape:stockid="TriangleOutL"
orient="auto"
refY="0"
refX="0"
id="TriangleOutL-9"
style="overflow:visible"
inkscape:isstock="true">
<path
inkscape:connector-curvature="0"
id="path12151-0"
d="M 5.77,0 -2.88,5 V -5 Z"
style="fill:#0081d5;fill-opacity:1;fill-rule:evenodd;stroke:#0081d5;stroke-width:1pt;stroke-opacity:1"
transform="scale(0.8)" />
</marker>
<marker
inkscape:stockid="TriangleInL"
orient="auto"
refY="0"
refX="0"
id="TriangleInL-9"
style="overflow:visible"
inkscape:isstock="true">
<path
inkscape:connector-curvature="0"
id="path12142-6"
d="M 5.77,0 -2.88,5 V -5 Z"
style="fill:#0081d5;fill-opacity:1;fill-rule:evenodd;stroke:#0081d5;stroke-width:1pt;stroke-opacity:1"
transform="scale(-0.8)" />
</marker>
<marker
inkscape:isstock="true"
style="overflow:visible"
id="marker23801-7"
refX="0"
refY="0"
orient="auto"
inkscape:stockid="TriangleOutL">
<path
inkscape:connector-curvature="0"
transform="scale(0.8)"
style="fill:#0081d5;fill-opacity:1;fill-rule:evenodd;stroke:#0081d5;stroke-width:1pt;stroke-opacity:1"
d="M 5.77,0 -2.88,5 V -5 Z"
id="path23799-7" />
</marker>
<marker
inkscape:stockid="TriangleInL"
orient="auto"
refY="0"
refX="0"
id="TriangleInL-9-7"
style="overflow:visible"
inkscape:isstock="true">
<path
inkscape:connector-curvature="0"
id="path12142-6-1"
d="M 5.77,0 -2.88,5 V -5 Z"
style="fill:#0081d5;fill-opacity:1;fill-rule:evenodd;stroke:#0081d5;stroke-width:1pt;stroke-opacity:1"
transform="scale(-0.8)" />
</marker>
<marker
inkscape:isstock="true"
style="overflow:visible"
id="marker23801-7-2"
refX="0"
refY="0"
orient="auto"
inkscape:stockid="TriangleOutL">
<path
inkscape:connector-curvature="0"
transform="scale(0.8)"
style="fill:#0081d5;fill-opacity:1;fill-rule:evenodd;stroke:#0081d5;stroke-width:1pt;stroke-opacity:1"
d="M 5.77,0 -2.88,5 V -5 Z"
id="path23799-7-2" />
</marker>
<marker
inkscape:stockid="TriangleInL"
orient="auto"
refY="0"
refX="0"
id="TriangleInL-9-5"
style="overflow:visible"
inkscape:isstock="true">
<path
inkscape:connector-curvature="0"
id="path12142-6-0"
d="M 5.77,0 -2.88,5 V -5 Z"
style="fill:#0081d5;fill-opacity:1;fill-rule:evenodd;stroke:#0081d5;stroke-width:1pt;stroke-opacity:1"
transform="scale(-0.8)" />
</marker>
<marker
inkscape:isstock="true"
style="overflow:visible"
id="marker23801-7-9"
refX="0"
refY="0"
orient="auto"
inkscape:stockid="TriangleOutL">
<path
inkscape:connector-curvature="0"
transform="scale(0.8)"
style="fill:#0081d5;fill-opacity:1;fill-rule:evenodd;stroke:#0081d5;stroke-width:1pt;stroke-opacity:1"
d="M 5.77,0 -2.88,5 V -5 Z"
id="path23799-7-0" />
</marker>
<marker
inkscape:stockid="TriangleInL"
orient="auto"
refY="0"
refX="0"
id="TriangleInL-9-5-0"
style="overflow:visible"
inkscape:isstock="true">
<path
inkscape:connector-curvature="0"
id="path12142-6-0-1"
d="M 5.77,0 -2.88,5 V -5 Z"
style="fill:#0081d5;fill-opacity:1;fill-rule:evenodd;stroke:#0081d5;stroke-width:1pt;stroke-opacity:1"
transform="scale(-0.8)" />
</marker>
<marker
inkscape:isstock="true"
style="overflow:visible"
id="marker23801-7-9-3"
refX="0"
refY="0"
orient="auto"
inkscape:stockid="TriangleOutL">
<path
inkscape:connector-curvature="0"
transform="scale(0.8)"
style="fill:#0081d5;fill-opacity:1;fill-rule:evenodd;stroke:#0081d5;stroke-width:1pt;stroke-opacity:1"
d="M 5.77,0 -2.88,5 V -5 Z"
id="path23799-7-0-7" />
</marker>
<marker
inkscape:stockid="TriangleInL"
orient="auto"
refY="0"
refX="0"
id="TriangleInL-7"
style="overflow:visible"
inkscape:isstock="true">
<path
inkscape:connector-curvature="0"
id="path12142-5"
d="M 5.77,0 -2.88,5 V -5 Z"
style="fill:#0081d5;fill-opacity:1;fill-rule:evenodd;stroke:#0081d5;stroke-width:1pt;stroke-opacity:1"
transform="scale(-0.8)" />
</marker>
<marker
inkscape:isstock="true"
style="overflow:visible"
id="marker23801-6"
refX="0"
refY="0"
orient="auto"
inkscape:stockid="TriangleOutL">
<path
inkscape:connector-curvature="0"
transform="scale(0.8)"
style="fill:#0081d5;fill-opacity:1;fill-rule:evenodd;stroke:#0081d5;stroke-width:1pt;stroke-opacity:1"
d="M 5.77,0 -2.88,5 V -5 Z"
id="path23799-5" />
</marker>
<marker
inkscape:stockid="TriangleInL"
orient="auto"
refY="0"
refX="0"
id="TriangleInL-7-1"
style="overflow:visible"
inkscape:isstock="true">
<path
inkscape:connector-curvature="0"
id="path12142-5-0"
d="M 5.77,0 -2.88,5 V -5 Z"
style="fill:#0081d5;fill-opacity:1;fill-rule:evenodd;stroke:#0081d5;stroke-width:1pt;stroke-opacity:1"
transform="scale(-0.8)" />
</marker>
<marker
inkscape:isstock="true"
style="overflow:visible"
id="marker23801-6-6"
refX="0"
refY="0"
orient="auto"
inkscape:stockid="TriangleOutL">
<path
inkscape:connector-curvature="0"
transform="scale(0.8)"
style="fill:#0081d5;fill-opacity:1;fill-rule:evenodd;stroke:#0081d5;stroke-width:1pt;stroke-opacity:1"
d="M 5.77,0 -2.88,5 V -5 Z"
id="path23799-5-3" />
</marker>
<marker
inkscape:stockid="TriangleInL"
orient="auto"
refY="0"
refX="0"
id="TriangleInL-0"
style="overflow:visible"
inkscape:isstock="true">
<path
inkscape:connector-curvature="0"
id="path12142-61"
d="M 5.77,0 -2.88,5 V -5 Z"
style="fill:#0081d5;fill-opacity:1;fill-rule:evenodd;stroke:#0081d5;stroke-width:1pt;stroke-opacity:1"
transform="scale(-0.8)" />
</marker>
<marker
inkscape:isstock="true"
style="overflow:visible"
id="marker23801-5"
refX="0"
refY="0"
orient="auto"
inkscape:stockid="TriangleOutL">
<path
inkscape:connector-curvature="0"
transform="scale(0.8)"
style="fill:#0081d5;fill-opacity:1;fill-rule:evenodd;stroke:#0081d5;stroke-width:1pt;stroke-opacity:1"
d="M 5.77,0 -2.88,5 V -5 Z"
id="path23799-54" />
</marker>
<marker
inkscape:stockid="TriangleInL"
orient="auto"
refY="0"
refX="0"
id="TriangleInL-74"
style="overflow:visible"
inkscape:isstock="true">
<path
inkscape:connector-curvature="0"
id="path12142-52"
d="M 5.77,0 -2.88,5 V -5 Z"
style="fill:#0081d5;fill-opacity:1;fill-rule:evenodd;stroke:#0081d5;stroke-width:1pt;stroke-opacity:1"
transform="scale(-0.8)" />
</marker>
<marker
inkscape:isstock="true"
style="overflow:visible"
id="marker23801-54"
refX="0"
refY="0"
orient="auto"
inkscape:stockid="TriangleOutL">
<path
inkscape:connector-curvature="0"
transform="scale(0.8)"
style="fill:#0081d5;fill-opacity:1;fill-rule:evenodd;stroke:#0081d5;stroke-width:1pt;stroke-opacity:1"
d="M 5.77,0 -2.88,5 V -5 Z"
id="path23799-74" />
</marker>
<marker
inkscape:stockid="TriangleInL"
orient="auto"
refY="0"
refX="0"
id="TriangleInL-74-0"
style="overflow:visible"
inkscape:isstock="true">
<path
inkscape:connector-curvature="0"
id="path12142-52-7"
d="M 5.77,0 -2.88,5 V -5 Z"
style="fill:#0081d5;fill-opacity:1;fill-rule:evenodd;stroke:#0081d5;stroke-width:1pt;stroke-opacity:1"
transform="scale(-0.8)" />
</marker>
<marker
inkscape:isstock="true"
style="overflow:visible"
id="marker23801-54-8"
refX="0"
refY="0"
orient="auto"
inkscape:stockid="TriangleOutL">
<path
inkscape:connector-curvature="0"
transform="scale(0.8)"
style="fill:#0081d5;fill-opacity:1;fill-rule:evenodd;stroke:#0081d5;stroke-width:1pt;stroke-opacity:1"
d="M 5.77,0 -2.88,5 V -5 Z"
id="path23799-74-6" />
</marker>
<marker
inkscape:stockid="TriangleInL"
orient="auto"
refY="0"
refX="0"
id="TriangleInL-8"
style="overflow:visible"
inkscape:isstock="true">
<path
id="path12142-8"
d="M 5.77,0 -2.88,5 V -5 Z"
style="fill:#0081d5;fill-opacity:1;fill-rule:evenodd;stroke:#0081d5;stroke-width:1pt;stroke-opacity:1"
transform="scale(-0.8)" />
</marker>
<marker
inkscape:isstock="true"
style="overflow:visible"
id="marker23801-3"
refX="0"
refY="0"
orient="auto"
inkscape:stockid="TriangleOutL">
<path
transform="scale(0.8)"
style="fill:#0081d5;fill-opacity:1;fill-rule:evenodd;stroke:#0081d5;stroke-width:1pt;stroke-opacity:1"
d="M 5.77,0 -2.88,5 V -5 Z"
id="path23799-52" />
</marker>
</defs>
<sodipodi:namedview
id="base"
pagecolor="#ffffff"
bordercolor="#666666"
borderopacity="1.0"
inkscape:pageopacity="0.0"
inkscape:pageshadow="2"
inkscape:zoom="0.80852013"
inkscape:cx="337.03552"
inkscape:cy="189.85303"
inkscape:document-units="mm"
inkscape:current-layer="layer8"
showgrid="false"
inkscape:window-width="1960"
inkscape:window-height="1178"
inkscape:window-x="0"
inkscape:window-y="44"
inkscape:window-maximized="0"
inkscape:snap-global="false"
showguides="false"
inkscape:document-rotation="0"
lock-margins="true"
fit-margin-top="2"
fit-margin-left="2"
fit-margin-right="2"
fit-margin-bottom="2"
inkscape:showpageshadow="2"
inkscape:pagecheckerboard="0"
inkscape:deskcolor="#d1d1d1" />
<metadata
id="metadata19841">
<rdf:RDF />
</metadata>
<g
inkscape:groupmode="layer"
id="layer9"
inkscape:label="Layer 4"
style="display:inline"
transform="translate(-50.901726,-151.02664)" />
<g
inkscape:label="Layer 1"
inkscape:groupmode="layer"
id="layer1"
transform="translate(-50.901726,-151.02664)">
<path
style="fill:none;stroke:#895502;stroke-width:0.5;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
d="m 122.04879,192.51551 10.68381,-10.75397 -0.009,-2.92062"
id="path20805"
inkscape:connector-curvature="0"
sodipodi:nodetypes="ccc" />
<path
style="fill:none;stroke:#895502;stroke-width:0.619834;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
d="m 54.199347,190.45327 -0.0034,2.392 67.339143,-1.9e-4 v -2.39132"
id="path20803"
inkscape:connector-curvature="0"
sodipodi:nodetypes="cccc" />
<path
style="fill:none;stroke:#895502;stroke-width:0.5;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
d="M 54.041006,164.19702 64.50364,153.58053"
id="path20805-1-9"
inkscape:connector-curvature="0"
sodipodi:nodetypes="cc" />
<path
style="fill:none;stroke:#895502;stroke-width:0.629986;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
d="m 64.326232,153.65354 68.633098,0.008"
id="path20805-1-4"
inkscape:connector-curvature="0"
sodipodi:nodetypes="cc" />
</g>
<g
inkscape:groupmode="layer"
id="layer8"
inkscape:label="Layer 3"
transform="translate(-50.901726,-151.02664)">
<path
style="fill:#fcb23c;fill-opacity:1;stroke:#545454;stroke-width:0.529167;stroke-linecap:round"
d="m 54.195947,192.84527 67.339143,-1.9e-4 11.19751,-11.08354 0.11204,-2.74697 -78.682805,11.08537 z"
id="path2" />
<path
style="fill:#fcb23c;fill-opacity:1;stroke:#545454;stroke-width:0.529167;stroke-linecap:round"
d="m 54.040972,164.19705 10.462634,-10.61649 68.278984,-0.0652 0.0668,2.59461 -11.49568,10.89781 0.48952,-2.55692 z"
id="path1" />
<path
style="display:inline;fill:#cccccc;fill-opacity:1;stroke:none;stroke-width:0.264583px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
d="m 79.91759,167.00765 39.26361,1.66204 13.6126,-12.67526 -0.0702,22.84649 -10.60793,10.80566 z"
id="path20574"
inkscape:connector-curvature="0"
sodipodi:nodetypes="cccccc" />
<rect
style="opacity:1;fill:#cccccc;fill-opacity:1;stroke:#474747;stroke-width:0.625544;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
id="rect20534"
width="67.191879"
height="23.092167"
x="54.161835"
y="167.00778" />
<text
xml:space="preserve"
style="font-style:normal;font-weight:normal;font-size:7.5037px;line-height:1.25;font-family:sans-serif;letter-spacing:0px;word-spacing:0px;fill:#0081d5;fill-opacity:1;stroke:none;stroke-width:0.187593"
x="61.715302"
y="186.69984"
id="text21059"><tspan
sodipodi:role="line"
id="tspan21057"
x="61.715302"
y="186.69984"
style="fill:#0081d5;fill-opacity:1;stroke-width:0.187593">T</tspan></text>
<path
style="fill:none;stroke:#895502;stroke-width:0.5;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
d="m 121.84323,164.45086 10.93939,-10.9355"
id="path20805-1"
inkscape:connector-curvature="0"
sodipodi:nodetypes="cc" />
<text
xml:space="preserve"
style="font-style:normal;font-weight:normal;font-size:9.15486px;line-height:1.25;font-family:sans-serif;letter-spacing:0px;word-spacing:0px;fill:#0081d5;fill-opacity:1;stroke:none;stroke-width:0.228872"
x="56.627808"
y="179.02429"
id="text23789"><tspan
sodipodi:role="line"
id="tspan23787"
x="56.627808"
y="179.02429"
style="fill:#0081d5;fill-opacity:1;stroke-width:0.228872">H</tspan></text>
<path
style="fill:none;stroke:#0081d5;stroke-width:0.3;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1;marker-start:url(#TriangleInL);marker-end:url(#marker23801)"
d="M 56.546083,188.04342 V 169.08263"
id="path23791"
inkscape:connector-curvature="0"
sodipodi:nodetypes="cc" />
<path
style="fill:none;stroke:#0081d5;stroke-width:0.250923;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1;marker-start:url(#TriangleInL-8);marker-end:url(#marker23801-3)"
d="M 80.029497,181.46964 H 93.294174"
id="path23791-2"
inkscape:connector-curvature="0"
sodipodi:nodetypes="cc"
inkscape:transform-center-x="4.2335716"
inkscape:transform-center-y="-8.4721688" />
<text
xml:space="preserve"
style="font-style:normal;font-weight:normal;font-size:9.15486px;line-height:1.25;font-family:sans-serif;letter-spacing:0px;word-spacing:0px;fill:#0081d5;fill-opacity:1;stroke:none;stroke-width:0.228872"
x="87.574654"
y="162.95206"
id="text23789-9" />
<path
style="fill:none;stroke:#0081d5;stroke-width:0.3;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1;marker-start:url(#TriangleInL-7);marker-end:url(#marker23801-6)"
d="m 89.639803,162.80003 7.50755,-7.7658"
id="path23791-4"
inkscape:connector-curvature="0"
sodipodi:nodetypes="cc" />
<text
xml:space="preserve"
style="font-style:normal;font-weight:normal;font-size:6.2411px;line-height:1.25;font-family:sans-serif;letter-spacing:0px;word-spacing:0px;fill:#0081d5;fill-opacity:1;stroke:none;stroke-width:0.156027"
x="87.845589"
y="159.39813"
id="text21059-1-3-2"><tspan
sodipodi:role="line"
id="tspan21057-1-0-2"
x="87.845589"
y="159.39813"
style="fill:#0081d5;fill-opacity:1;stroke-width:0.156027">L</tspan></text>
<path
style="fill:none;stroke:#474747;stroke-width:0.5;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
d="m 122.05054,190.09836 10.7941,-11.08379"
id="path20538-6"
inkscape:connector-curvature="0"
inkscape:transform-center-x="0.65481035"
inkscape:transform-center-y="7.4835468"
sodipodi:nodetypes="cc" />
<path
style="fill:none;stroke:#474747;stroke-width:0.5;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
d="m 132.84464,179.01457 0.0187,-23.86743"
id="path20538-6-1"
inkscape:connector-curvature="0"
inkscape:transform-center-x="0.65481035"
inkscape:transform-center-y="7.4835468"
sodipodi:nodetypes="cc" />
<rect
style="opacity:1;fill:#fcb23c;fill-opacity:1;stroke:#895502;stroke-width:0.614626;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
id="rect6104"
width="67.207901"
height="2.1072214"
x="54.151272"
y="164.32817"
ry="0" />
<path
style="fill:none;stroke:#895502;stroke-width:0.5;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
d="m 122.05054,167.00938 10.79885,-10.89941 0.008,-2.19227"
id="path20805-3"
inkscape:connector-curvature="0"
sodipodi:nodetypes="ccc" />
<path
style="fill:none;stroke:#474747;stroke-width:0.5;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:3, 0.5;stroke-dashoffset:0;stroke-opacity:1"
d="m 78.447673,177.00008 9.624797,-9.8911"
id="path20538-6-8"
inkscape:connector-curvature="0"
inkscape:transform-center-x="0.65481035"
inkscape:transform-center-y="7.4835468"
sodipodi:nodetypes="cc" />
<path
style="fill:none;stroke:#474747;stroke-width:0.5;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:3, 0.5;stroke-dashoffset:0;stroke-opacity:1"
d="m 78.425464,179.66243 9.624797,-9.8911"
id="path20538-6-8-0"
inkscape:connector-curvature="0"
inkscape:transform-center-x="0.65481035"
inkscape:transform-center-y="7.4835468"
sodipodi:nodetypes="cc" />
<path
style="fill:none;stroke:#474747;stroke-width:0.5;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:3, 0.5;stroke-dashoffset:0;stroke-opacity:1"
d="m 71.760429,176.83271 9.624797,-9.8911"
id="path20538-6-8-0-3"
inkscape:connector-curvature="0"
inkscape:transform-center-x="0.65481035"
inkscape:transform-center-y="7.4835468"
sodipodi:nodetypes="cc" />
<path
style="fill:none;stroke:#474747;stroke-width:0.5;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:3, 0.5;stroke-dashoffset:0;stroke-opacity:1"
d="m 87.88075,170.06683 0.07597,-3.05506"
id="path20538-6-8-0-6"
inkscape:connector-curvature="0"
inkscape:transform-center-x="0.65481035"
inkscape:transform-center-y="7.4835468"
sodipodi:nodetypes="cc" />
<path
style="fill:none;stroke:#474747;stroke-width:0.5;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:3, 0.5;stroke-dashoffset:0;stroke-opacity:1"
d="m 111.28813,169.76512 0.076,-3.05506"
id="path20538-6-8-0-6-9"
inkscape:connector-curvature="0"
inkscape:transform-center-x="0.65481035"
inkscape:transform-center-y="7.4835468"
sodipodi:nodetypes="cc" />
<path
style="fill:none;stroke:#0081d5;stroke-width:0.3;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:2.4, 0.3;stroke-dashoffset:0;stroke-opacity:1"
d="m 71.561356,179.69463 -5.224783,0.0131"
id="path23791-7"
inkscape:connector-curvature="0"
sodipodi:nodetypes="cc" />
<path
style="fill:none;stroke:#0081d5;stroke-width:0.3;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:2.4, 0.3;stroke-dashoffset:0;stroke-opacity:1"
d="m 71.51701,176.88556 -5.224783,0.0131"
id="path23791-7-3"
inkscape:connector-curvature="0"
sodipodi:nodetypes="cc" />
<text
xml:space="preserve"
style="font-style:normal;font-weight:normal;font-size:7.5037px;line-height:1.25;font-family:sans-serif;letter-spacing:0px;word-spacing:0px;fill:#0081d5;fill-opacity:1;stroke:none;stroke-width:0.187593"
x="71.381172"
y="189.32043"
id="text21059-5"><tspan
sodipodi:role="line"
id="tspan21057-6"
x="71.381172"
y="189.32043"
style="fill:#0081d5;fill-opacity:1;stroke-width:0.187593">W</tspan></text>
<text
xml:space="preserve"
style="font-style:normal;font-weight:normal;font-size:7.5037px;line-height:1.25;font-family:sans-serif;letter-spacing:0px;word-spacing:0px;fill:#0081d5;fill-opacity:1;stroke:none;stroke-width:0.187593"
x="84.089783"
y="188.25977"
id="text21059-5-7"><tspan
sodipodi:role="line"
id="tspan21057-6-1"
x="84.089783"
y="188.25977"
style="fill:#0081d5;fill-opacity:1;stroke-width:0.187593">S</tspan></text>
<path
style="fill:none;stroke:#0081d5;stroke-width:0.3;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:2.4, 0.3;stroke-dashoffset:0;stroke-opacity:1"
d="m 71.648638,179.5799 -0.0097,2.66362"
id="path23791-7-9"
inkscape:connector-curvature="0"
sodipodi:nodetypes="cc" />
<path
style="fill:none;stroke:#0081d5;stroke-width:0.3;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:2.4, 0.3;stroke-dashoffset:0;stroke-opacity:1"
d="m 78.468682,179.60109 -0.0097,2.61685"
id="path23791-7-9-3"
inkscape:connector-curvature="0"
sodipodi:nodetypes="cc" />
<path
style="fill:none;stroke:#0081d5;stroke-width:0.3;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:2.4, 0.3;stroke-dashoffset:0;stroke-opacity:1"
d="m 94.848919,179.80535 -0.0097,2.61685"
id="path23791-7-9-3-1"
inkscape:connector-curvature="0"
sodipodi:nodetypes="cc" />
<path
style="fill:none;stroke:#0081d5;stroke-width:0.25;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1;marker-start:url(#TriangleInL-74);marker-end:url(#marker23801-54)"
d="m 76.876847,181.51957 -3.624842,-0.0298"
id="path23791-43"
inkscape:connector-curvature="0"
sodipodi:nodetypes="cc" />
<text
xml:space="preserve"
style="font-style:normal;font-weight:normal;font-size:10.5833px;line-height:1.25;font-family:sans-serif;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.264583"
x="58.652298"
y="173.61502"
id="text15381" />
</g>
<g
inkscape:groupmode="layer"
id="layer7"
inkscape:label="Layer 2"
transform="translate(-50.901726,-151.02664)">
<rect
style="opacity:1;fill:#fcb23c;fill-opacity:1;stroke:#895502;stroke-width:0.499178;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
id="rect20424"
width="6.6496596"
height="2.6584671"
x="71.743835"
y="176.97217" />
<path
style="fill:none;stroke:#474747;stroke-width:0.5;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:3, 0.5;stroke-dashoffset:0;stroke-opacity:1"
d="m 101.6132,176.95663 9.62485,-9.8911"
id="path20538-6-8-8"
inkscape:connector-curvature="0"
inkscape:transform-center-x="0.65481035"
inkscape:transform-center-y="7.4835468"
sodipodi:nodetypes="cc" />
<path
style="fill:none;stroke:#474747;stroke-width:0.5;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:3, 0.5;stroke-dashoffset:0;stroke-opacity:1"
d="m 101.98778,179.66243 9.62485,-9.8911"
id="path20538-6-8-8-4"
inkscape:connector-curvature="0"
inkscape:transform-center-x="0.65481035"
inkscape:transform-center-y="7.4835468"
sodipodi:nodetypes="cc" />
<path
style="fill:none;stroke:#474747;stroke-width:0.5;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:3, 0.5;stroke-dashoffset:0;stroke-opacity:1"
d="m 94.925946,176.78926 9.624824,-9.8911"
id="path20538-6-8-0-3-0"
inkscape:connector-curvature="0"
inkscape:transform-center-x="0.65481035"
inkscape:transform-center-y="7.4835468"
sodipodi:nodetypes="cc" />
<rect
style="fill:#fcb23c;fill-opacity:1;stroke:#895502;stroke-width:0.499178;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
id="rect20424-4"
width="6.6496596"
height="2.6584671"
x="94.909355"
y="176.92873" />
<path
style="fill:none;stroke:#0081d5;stroke-width:0.3;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1;marker-end:url(#TriangleOutL)"
d="m 68.396624,187.21173 v -5.41497"
id="path21071"
inkscape:connector-curvature="0"
sodipodi:nodetypes="cc" />
<path
style="fill:none;stroke:#0081d5;stroke-width:0.3;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1;marker-end:url(#TriangleOutL-9)"
d="m 68.307853,169.42208 v 5.41497"
id="path21071-8"
inkscape:connector-curvature="0"
sodipodi:nodetypes="cc" />
</g>
</svg>

After

Width:  |  Height:  |  Size: 32 KiB

View File

@ -0,0 +1,834 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<svg
width="85mm"
height="44mm"
viewBox="0 0 85 44"
version="1.1"
id="svg19844"
inkscape:version="1.4 (e7c3feb1, 2024-10-09)"
sodipodi:docname="coupled_stripline.svg"
inkscape:export-filename="/Users/jeff/kicad_dev/kicad/bitmaps_png/png_other/stripline.png"
inkscape:export-xdpi="96"
inkscape:export-ydpi="96"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns="http://www.w3.org/2000/svg"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#">
<defs
id="defs19838">
<marker
inkscape:stockid="TriangleInL"
orient="auto"
refY="0"
refX="0"
id="TriangleInL"
style="overflow:visible"
inkscape:isstock="true">
<path
id="path12142"
d="M 5.77,0 -2.88,5 V -5 Z"
style="fill:#0081d5;fill-opacity:1;fill-rule:evenodd;stroke:#0081d5;stroke-width:1pt;stroke-opacity:1"
transform="scale(-0.8)" />
</marker>
<marker
inkscape:stockid="Arrow2Lstart"
orient="auto"
refY="0"
refX="0"
id="Arrow2Lstart"
style="overflow:visible"
inkscape:isstock="true">
<path
id="path12027"
style="fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:0.625;stroke-linejoin:round;stroke-opacity:1"
d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z"
transform="matrix(1.1,0,0,1.1,1.1,0)" />
</marker>
<marker
inkscape:isstock="true"
style="overflow:visible"
id="marker23801"
refX="0"
refY="0"
orient="auto"
inkscape:stockid="TriangleOutL">
<path
transform="scale(0.8)"
style="fill:#0081d5;fill-opacity:1;fill-rule:evenodd;stroke:#0081d5;stroke-width:1pt;stroke-opacity:1"
d="M 5.77,0 -2.88,5 V -5 Z"
id="path23799" />
</marker>
<marker
inkscape:stockid="TriangleOutL"
orient="auto"
refY="0"
refX="0"
id="TriangleOutL"
style="overflow:visible"
inkscape:isstock="true"
inkscape:collect="always">
<path
id="path12151"
d="M 5.77,0 -2.88,5 V -5 Z"
style="fill:#0081d5;fill-opacity:1;fill-rule:evenodd;stroke:#0081d5;stroke-width:1pt;stroke-opacity:1"
transform="scale(0.8)" />
</marker>
<marker
style="overflow:visible"
id="DistanceEnd"
refX="0"
refY="0"
orient="auto"
inkscape:stockid="DistanceEnd"
inkscape:isstock="true">
<g
id="g2301"
style="fill:#0081d5;fill-opacity:1;stroke:#0081d5;stroke-opacity:1">
<path
style="fill:#0081d5;fill-opacity:1;stroke:#0081d5;stroke-width:1.15;stroke-linecap:square;stroke-opacity:1"
d="M 0,0 H -2"
id="path2316" />
<path
style="fill:#0081d5;fill-opacity:1;fill-rule:evenodd;stroke:#0081d5;stroke-opacity:1"
d="m 0,0 -13,4 4,-4 -4,-4 z"
id="path2312" />
<path
style="fill:#0081d5;fill-opacity:1;stroke:#0081d5;stroke-width:1;stroke-linecap:square;stroke-opacity:1"
d="M 0,-4 V 40"
id="path2314" />
</g>
</marker>
<marker
style="overflow:visible"
id="DistanceStart"
refX="0"
refY="0"
orient="auto"
inkscape:stockid="DistanceStart"
inkscape:isstock="true">
<g
id="g2300"
style="fill:#0081d5;fill-opacity:1;stroke:#0081d5;stroke-opacity:1">
<path
style="fill:#0081d5;fill-opacity:1;stroke:#0081d5;stroke-width:1.15;stroke-linecap:square;stroke-opacity:1"
d="M 0,0 H 2"
id="path2306" />
<path
style="fill:#0081d5;fill-opacity:1;fill-rule:evenodd;stroke:#0081d5;stroke-opacity:1"
d="M 0,0 13,4 9,0 13,-4 Z"
id="path2302" />
<path
style="fill:#0081d5;fill-opacity:1;stroke:#0081d5;stroke-width:1;stroke-linecap:square;stroke-opacity:1"
d="M 0,-4 V 40"
id="path2304" />
</g>
</marker>
<marker
inkscape:stockid="Arrow2Lend"
orient="auto"
refY="0"
refX="0"
id="marker21133"
style="overflow:visible"
inkscape:isstock="true">
<path
id="path21131"
style="fill:#0081d5;fill-opacity:1;fill-rule:evenodd;stroke:#0081d5;stroke-width:0.625;stroke-linejoin:round;stroke-opacity:1"
d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z"
transform="matrix(-1.1,0,0,-1.1,-1.1,0)" />
</marker>
<marker
inkscape:stockid="RazorWire"
id="RazorWire"
refX="0"
refY="0"
orient="auto"
style="overflow:visible"
inkscape:isstock="true">
<path
id="path12241"
transform="scale(0.8)"
style="fill:#0081d5;fill-opacity:1;fill-rule:evenodd;stroke:#0081d5;stroke-width:0.1pt;stroke-opacity:1"
d="m 0.02272727,-0.74009011 v 1.4375 L -7.7585227,3.0099099 H 10.678977 L 3.4914773,0.69740989 v -1.4375 L 10.741477,-2.8963401 H -7.7272727 Z" />
</marker>
<marker
inkscape:stockid="Arrow2Lend"
orient="auto"
refY="0"
refX="0"
id="Arrow2Lend"
style="overflow:visible"
inkscape:isstock="true">
<path
id="path12030"
style="fill:#0081d5;fill-opacity:1;fill-rule:evenodd;stroke:#0081d5;stroke-width:0.625;stroke-linejoin:round;stroke-opacity:1"
d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z"
transform="matrix(-1.1,0,0,-1.1,-1.1,0)" />
</marker>
<marker
inkscape:stockid="TriangleOutL"
orient="auto"
refY="0"
refX="0"
id="TriangleOutL-9"
style="overflow:visible"
inkscape:isstock="true">
<path
inkscape:connector-curvature="0"
id="path12151-0"
d="M 5.77,0 -2.88,5 V -5 Z"
style="fill:#0081d5;fill-opacity:1;fill-rule:evenodd;stroke:#0081d5;stroke-width:1pt;stroke-opacity:1"
transform="scale(0.8)" />
</marker>
<marker
inkscape:stockid="TriangleInL"
orient="auto"
refY="0"
refX="0"
id="TriangleInL-9"
style="overflow:visible"
inkscape:isstock="true">
<path
inkscape:connector-curvature="0"
id="path12142-6"
d="M 5.77,0 -2.88,5 V -5 Z"
style="fill:#0081d5;fill-opacity:1;fill-rule:evenodd;stroke:#0081d5;stroke-width:1pt;stroke-opacity:1"
transform="scale(-0.8)" />
</marker>
<marker
inkscape:isstock="true"
style="overflow:visible"
id="marker23801-7"
refX="0"
refY="0"
orient="auto"
inkscape:stockid="TriangleOutL">
<path
inkscape:connector-curvature="0"
transform="scale(0.8)"
style="fill:#0081d5;fill-opacity:1;fill-rule:evenodd;stroke:#0081d5;stroke-width:1pt;stroke-opacity:1"
d="M 5.77,0 -2.88,5 V -5 Z"
id="path23799-7" />
</marker>
<marker
inkscape:stockid="TriangleInL"
orient="auto"
refY="0"
refX="0"
id="TriangleInL-9-7"
style="overflow:visible"
inkscape:isstock="true">
<path
inkscape:connector-curvature="0"
id="path12142-6-1"
d="M 5.77,0 -2.88,5 V -5 Z"
style="fill:#0081d5;fill-opacity:1;fill-rule:evenodd;stroke:#0081d5;stroke-width:1pt;stroke-opacity:1"
transform="scale(-0.8)" />
</marker>
<marker
inkscape:isstock="true"
style="overflow:visible"
id="marker23801-7-2"
refX="0"
refY="0"
orient="auto"
inkscape:stockid="TriangleOutL">
<path
inkscape:connector-curvature="0"
transform="scale(0.8)"
style="fill:#0081d5;fill-opacity:1;fill-rule:evenodd;stroke:#0081d5;stroke-width:1pt;stroke-opacity:1"
d="M 5.77,0 -2.88,5 V -5 Z"
id="path23799-7-2" />
</marker>
<marker
inkscape:stockid="TriangleInL"
orient="auto"
refY="0"
refX="0"
id="TriangleInL-9-5"
style="overflow:visible"
inkscape:isstock="true">
<path
inkscape:connector-curvature="0"
id="path12142-6-0"
d="M 5.77,0 -2.88,5 V -5 Z"
style="fill:#0081d5;fill-opacity:1;fill-rule:evenodd;stroke:#0081d5;stroke-width:1pt;stroke-opacity:1"
transform="scale(-0.8)" />
</marker>
<marker
inkscape:isstock="true"
style="overflow:visible"
id="marker23801-7-9"
refX="0"
refY="0"
orient="auto"
inkscape:stockid="TriangleOutL">
<path
inkscape:connector-curvature="0"
transform="scale(0.8)"
style="fill:#0081d5;fill-opacity:1;fill-rule:evenodd;stroke:#0081d5;stroke-width:1pt;stroke-opacity:1"
d="M 5.77,0 -2.88,5 V -5 Z"
id="path23799-7-0" />
</marker>
<marker
inkscape:stockid="TriangleInL"
orient="auto"
refY="0"
refX="0"
id="TriangleInL-9-5-0"
style="overflow:visible"
inkscape:isstock="true">
<path
inkscape:connector-curvature="0"
id="path12142-6-0-1"
d="M 5.77,0 -2.88,5 V -5 Z"
style="fill:#0081d5;fill-opacity:1;fill-rule:evenodd;stroke:#0081d5;stroke-width:1pt;stroke-opacity:1"
transform="scale(-0.8)" />
</marker>
<marker
inkscape:isstock="true"
style="overflow:visible"
id="marker23801-7-9-3"
refX="0"
refY="0"
orient="auto"
inkscape:stockid="TriangleOutL">
<path
inkscape:connector-curvature="0"
transform="scale(0.8)"
style="fill:#0081d5;fill-opacity:1;fill-rule:evenodd;stroke:#0081d5;stroke-width:1pt;stroke-opacity:1"
d="M 5.77,0 -2.88,5 V -5 Z"
id="path23799-7-0-7" />
</marker>
<marker
inkscape:stockid="TriangleInL"
orient="auto"
refY="0"
refX="0"
id="TriangleInL-7"
style="overflow:visible"
inkscape:isstock="true">
<path
inkscape:connector-curvature="0"
id="path12142-5"
d="M 5.77,0 -2.88,5 V -5 Z"
style="fill:#0081d5;fill-opacity:1;fill-rule:evenodd;stroke:#0081d5;stroke-width:1pt;stroke-opacity:1"
transform="scale(-0.8)" />
</marker>
<marker
inkscape:isstock="true"
style="overflow:visible"
id="marker23801-6"
refX="0"
refY="0"
orient="auto"
inkscape:stockid="TriangleOutL">
<path
inkscape:connector-curvature="0"
transform="scale(0.8)"
style="fill:#0081d5;fill-opacity:1;fill-rule:evenodd;stroke:#0081d5;stroke-width:1pt;stroke-opacity:1"
d="M 5.77,0 -2.88,5 V -5 Z"
id="path23799-5" />
</marker>
<marker
inkscape:stockid="TriangleInL"
orient="auto"
refY="0"
refX="0"
id="TriangleInL-7-1"
style="overflow:visible"
inkscape:isstock="true">
<path
inkscape:connector-curvature="0"
id="path12142-5-0"
d="M 5.77,0 -2.88,5 V -5 Z"
style="fill:#0081d5;fill-opacity:1;fill-rule:evenodd;stroke:#0081d5;stroke-width:1pt;stroke-opacity:1"
transform="scale(-0.8)" />
</marker>
<marker
inkscape:isstock="true"
style="overflow:visible"
id="marker23801-6-6"
refX="0"
refY="0"
orient="auto"
inkscape:stockid="TriangleOutL">
<path
inkscape:connector-curvature="0"
transform="scale(0.8)"
style="fill:#0081d5;fill-opacity:1;fill-rule:evenodd;stroke:#0081d5;stroke-width:1pt;stroke-opacity:1"
d="M 5.77,0 -2.88,5 V -5 Z"
id="path23799-5-3" />
</marker>
<marker
inkscape:stockid="TriangleInL"
orient="auto"
refY="0"
refX="0"
id="TriangleInL-0"
style="overflow:visible"
inkscape:isstock="true">
<path
inkscape:connector-curvature="0"
id="path12142-61"
d="M 5.77,0 -2.88,5 V -5 Z"
style="fill:#0081d5;fill-opacity:1;fill-rule:evenodd;stroke:#0081d5;stroke-width:1pt;stroke-opacity:1"
transform="scale(-0.8)" />
</marker>
<marker
inkscape:isstock="true"
style="overflow:visible"
id="marker23801-5"
refX="0"
refY="0"
orient="auto"
inkscape:stockid="TriangleOutL">
<path
inkscape:connector-curvature="0"
transform="scale(0.8)"
style="fill:#0081d5;fill-opacity:1;fill-rule:evenodd;stroke:#0081d5;stroke-width:1pt;stroke-opacity:1"
d="M 5.77,0 -2.88,5 V -5 Z"
id="path23799-54" />
</marker>
<marker
inkscape:stockid="TriangleInL"
orient="auto"
refY="0"
refX="0"
id="TriangleInL-74"
style="overflow:visible"
inkscape:isstock="true">
<path
inkscape:connector-curvature="0"
id="path12142-52"
d="M 5.77,0 -2.88,5 V -5 Z"
style="fill:#0081d5;fill-opacity:1;fill-rule:evenodd;stroke:#0081d5;stroke-width:1pt;stroke-opacity:1"
transform="scale(-0.8)" />
</marker>
<marker
inkscape:isstock="true"
style="overflow:visible"
id="marker23801-54"
refX="0"
refY="0"
orient="auto"
inkscape:stockid="TriangleOutL">
<path
inkscape:connector-curvature="0"
transform="scale(0.8)"
style="fill:#0081d5;fill-opacity:1;fill-rule:evenodd;stroke:#0081d5;stroke-width:1pt;stroke-opacity:1"
d="M 5.77,0 -2.88,5 V -5 Z"
id="path23799-74" />
</marker>
<marker
inkscape:stockid="TriangleInL"
orient="auto"
refY="0"
refX="0"
id="TriangleInL-74-0"
style="overflow:visible"
inkscape:isstock="true">
<path
inkscape:connector-curvature="0"
id="path12142-52-7"
d="M 5.77,0 -2.88,5 V -5 Z"
style="fill:#0081d5;fill-opacity:1;fill-rule:evenodd;stroke:#0081d5;stroke-width:1pt;stroke-opacity:1"
transform="scale(-0.8)" />
</marker>
<marker
inkscape:isstock="true"
style="overflow:visible"
id="marker23801-54-8"
refX="0"
refY="0"
orient="auto"
inkscape:stockid="TriangleOutL">
<path
inkscape:connector-curvature="0"
transform="scale(0.8)"
style="fill:#0081d5;fill-opacity:1;fill-rule:evenodd;stroke:#0081d5;stroke-width:1pt;stroke-opacity:1"
d="M 5.77,0 -2.88,5 V -5 Z"
id="path23799-74-6" />
</marker>
<marker
inkscape:stockid="TriangleInL"
orient="auto"
refY="0"
refX="0"
id="TriangleInL-8"
style="overflow:visible"
inkscape:isstock="true">
<path
id="path12142-8"
d="M 5.77,0 -2.88,5 V -5 Z"
style="fill:#0081d5;fill-opacity:1;fill-rule:evenodd;stroke:#0081d5;stroke-width:1pt;stroke-opacity:1"
transform="scale(-0.8)" />
</marker>
<marker
inkscape:isstock="true"
style="overflow:visible"
id="marker23801-3"
refX="0"
refY="0"
orient="auto"
inkscape:stockid="TriangleOutL">
<path
transform="scale(0.8)"
style="fill:#0081d5;fill-opacity:1;fill-rule:evenodd;stroke:#0081d5;stroke-width:1pt;stroke-opacity:1"
d="M 5.77,0 -2.88,5 V -5 Z"
id="path23799-52" />
</marker>
</defs>
<sodipodi:namedview
id="base"
pagecolor="#ffffff"
bordercolor="#666666"
borderopacity="1.0"
inkscape:pageopacity="0.0"
inkscape:pageshadow="2"
inkscape:zoom="0.80852013"
inkscape:cx="337.03552"
inkscape:cy="189.85304"
inkscape:document-units="mm"
inkscape:current-layer="layer8"
showgrid="false"
inkscape:window-width="1960"
inkscape:window-height="1178"
inkscape:window-x="0"
inkscape:window-y="44"
inkscape:window-maximized="0"
inkscape:snap-global="false"
showguides="false"
inkscape:document-rotation="0"
lock-margins="true"
fit-margin-top="2"
fit-margin-left="2"
fit-margin-right="2"
fit-margin-bottom="2"
inkscape:showpageshadow="2"
inkscape:pagecheckerboard="0"
inkscape:deskcolor="#d1d1d1" />
<metadata
id="metadata19841">
<rdf:RDF />
</metadata>
<g
inkscape:groupmode="layer"
id="layer9"
inkscape:label="Layer 4"
style="display:inline"
transform="translate(-50.901726,-151.02664)" />
<g
inkscape:label="Layer 1"
inkscape:groupmode="layer"
id="layer1"
transform="translate(-50.901726,-151.02664)">
<path
style="fill:none;stroke:#895502;stroke-width:0.5;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
d="m 122.04879,192.51551 10.68381,-10.75397 -0.009,-2.92062"
id="path20805"
inkscape:connector-curvature="0"
sodipodi:nodetypes="ccc" />
<path
style="fill:none;stroke:#895502;stroke-width:0.619834;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
d="m 54.199347,190.45327 -0.0034,2.392 67.339143,-1.9e-4 v -2.39132"
id="path20803"
inkscape:connector-curvature="0"
sodipodi:nodetypes="cccc" />
<path
style="fill:none;stroke:#895502;stroke-width:0.5;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
d="M 54.041006,164.19702 64.50364,153.58053"
id="path20805-1-9"
inkscape:connector-curvature="0"
sodipodi:nodetypes="cc" />
<path
style="fill:none;stroke:#895502;stroke-width:0.629986;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
d="m 64.326232,153.65354 68.633098,0.008"
id="path20805-1-4"
inkscape:connector-curvature="0"
sodipodi:nodetypes="cc" />
</g>
<g
inkscape:groupmode="layer"
id="layer8"
inkscape:label="Layer 3"
transform="translate(-50.901726,-151.02664)">
<path
style="fill:#fcb23c;fill-opacity:1;stroke:#545454;stroke-width:0.529167;stroke-linecap:round"
d="m 54.195947,192.84527 67.339143,-1.9e-4 11.19751,-11.08354 0.11204,-2.74697 -78.682805,11.08537 z"
id="path2" />
<path
style="fill:#fcb23c;fill-opacity:1;stroke:#545454;stroke-width:0.529167;stroke-linecap:round"
d="m 54.040972,164.19705 10.462634,-10.61649 68.278984,-0.0652 0.0668,2.59461 -11.49568,10.89781 0.48952,-2.55692 z"
id="path1" />
<path
style="display:inline;fill:#cccccc;fill-opacity:1;stroke:none;stroke-width:0.264583px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
d="m 79.91759,167.00765 39.26361,1.66204 13.6126,-12.67526 -0.0702,22.84649 -10.60793,10.80566 z"
id="path20574"
inkscape:connector-curvature="0"
sodipodi:nodetypes="cccccc" />
<rect
style="opacity:1;fill:#cccccc;fill-opacity:1;stroke:#474747;stroke-width:0.625544;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
id="rect20534"
width="67.191879"
height="23.092167"
x="54.161835"
y="167.00778" />
<text
xml:space="preserve"
style="font-style:normal;font-weight:normal;font-size:7.5037px;line-height:1.25;font-family:sans-serif;letter-spacing:0px;word-spacing:0px;fill:#0081d5;fill-opacity:1;stroke:none;stroke-width:0.187593"
x="61.715302"
y="186.69984"
id="text21059"><tspan
sodipodi:role="line"
id="tspan21057"
x="61.715302"
y="186.69984"
style="fill:#0081d5;fill-opacity:1;stroke-width:0.187593">T</tspan></text>
<path
style="fill:none;stroke:#895502;stroke-width:0.5;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
d="m 121.84323,164.45086 10.93939,-10.9355"
id="path20805-1"
inkscape:connector-curvature="0"
sodipodi:nodetypes="cc" />
<text
xml:space="preserve"
style="font-style:normal;font-weight:normal;font-size:9.15486px;line-height:1.25;font-family:sans-serif;letter-spacing:0px;word-spacing:0px;fill:#0081d5;fill-opacity:1;stroke:none;stroke-width:0.228872"
x="56.627808"
y="179.02429"
id="text23789"><tspan
sodipodi:role="line"
id="tspan23787"
x="56.627808"
y="179.02429"
style="fill:#0081d5;fill-opacity:1;stroke-width:0.228872">H</tspan></text>
<path
style="fill:none;stroke:#0081d5;stroke-width:0.3;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1;marker-start:url(#TriangleInL);marker-end:url(#marker23801)"
d="M 56.546083,188.04342 V 169.08263"
id="path23791"
inkscape:connector-curvature="0"
sodipodi:nodetypes="cc" />
<path
style="fill:none;stroke:#0081d5;stroke-width:0.250923;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1;marker-start:url(#TriangleInL-8);marker-end:url(#marker23801-3)"
d="M 80.029497,181.46964 H 93.294174"
id="path23791-2"
inkscape:connector-curvature="0"
sodipodi:nodetypes="cc"
inkscape:transform-center-x="4.2335716"
inkscape:transform-center-y="-8.4721688" />
<text
xml:space="preserve"
style="font-style:normal;font-weight:normal;font-size:9.15486px;line-height:1.25;font-family:sans-serif;letter-spacing:0px;word-spacing:0px;fill:#0081d5;fill-opacity:1;stroke:none;stroke-width:0.228872"
x="87.574654"
y="162.95206"
id="text23789-9" />
<path
style="fill:none;stroke:#0081d5;stroke-width:0.3;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1;marker-start:url(#TriangleInL-7);marker-end:url(#marker23801-6)"
d="m 89.639803,162.80003 7.50755,-7.7658"
id="path23791-4"
inkscape:connector-curvature="0"
sodipodi:nodetypes="cc" />
<text
xml:space="preserve"
style="font-style:normal;font-weight:normal;font-size:6.2411px;line-height:1.25;font-family:sans-serif;letter-spacing:0px;word-spacing:0px;fill:#0081d5;fill-opacity:1;stroke:none;stroke-width:0.156027"
x="87.845589"
y="159.39813"
id="text21059-1-3-2"><tspan
sodipodi:role="line"
id="tspan21057-1-0-2"
x="87.845589"
y="159.39813"
style="fill:#0081d5;fill-opacity:1;stroke-width:0.156027">L</tspan></text>
<path
style="fill:none;stroke:#474747;stroke-width:0.5;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
d="m 122.05054,190.09836 10.7941,-11.08379"
id="path20538-6"
inkscape:connector-curvature="0"
inkscape:transform-center-x="0.65481035"
inkscape:transform-center-y="7.4835468"
sodipodi:nodetypes="cc" />
<path
style="fill:none;stroke:#474747;stroke-width:0.5;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
d="m 132.84464,179.01457 0.0187,-23.86743"
id="path20538-6-1"
inkscape:connector-curvature="0"
inkscape:transform-center-x="0.65481035"
inkscape:transform-center-y="7.4835468"
sodipodi:nodetypes="cc" />
<rect
style="opacity:1;fill:#fcb23c;fill-opacity:1;stroke:#895502;stroke-width:0.614626;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
id="rect6104"
width="67.207901"
height="2.1072214"
x="54.151272"
y="164.32817"
ry="0" />
<path
style="fill:none;stroke:#895502;stroke-width:0.5;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
d="m 122.05054,167.00938 10.79885,-10.89941 0.008,-2.19227"
id="path20805-3"
inkscape:connector-curvature="0"
sodipodi:nodetypes="ccc" />
<path
style="fill:none;stroke:#474747;stroke-width:0.5;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:3, 0.5;stroke-dashoffset:0;stroke-opacity:1"
d="m 78.447673,177.00008 9.624797,-9.8911"
id="path20538-6-8"
inkscape:connector-curvature="0"
inkscape:transform-center-x="0.65481035"
inkscape:transform-center-y="7.4835468"
sodipodi:nodetypes="cc" />
<path
style="fill:none;stroke:#474747;stroke-width:0.5;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:3, 0.5;stroke-dashoffset:0;stroke-opacity:1"
d="m 78.425464,179.66243 9.624797,-9.8911"
id="path20538-6-8-0"
inkscape:connector-curvature="0"
inkscape:transform-center-x="0.65481035"
inkscape:transform-center-y="7.4835468"
sodipodi:nodetypes="cc" />
<path
style="fill:none;stroke:#474747;stroke-width:0.5;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:3, 0.5;stroke-dashoffset:0;stroke-opacity:1"
d="m 71.760429,176.83271 9.624797,-9.8911"
id="path20538-6-8-0-3"
inkscape:connector-curvature="0"
inkscape:transform-center-x="0.65481035"
inkscape:transform-center-y="7.4835468"
sodipodi:nodetypes="cc" />
<path
style="fill:none;stroke:#474747;stroke-width:0.5;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:3, 0.5;stroke-dashoffset:0;stroke-opacity:1"
d="m 87.88075,170.06683 0.07597,-3.05506"
id="path20538-6-8-0-6"
inkscape:connector-curvature="0"
inkscape:transform-center-x="0.65481035"
inkscape:transform-center-y="7.4835468"
sodipodi:nodetypes="cc" />
<path
style="fill:none;stroke:#474747;stroke-width:0.5;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:3, 0.5;stroke-dashoffset:0;stroke-opacity:1"
d="m 111.28813,169.76512 0.076,-3.05506"
id="path20538-6-8-0-6-9"
inkscape:connector-curvature="0"
inkscape:transform-center-x="0.65481035"
inkscape:transform-center-y="7.4835468"
sodipodi:nodetypes="cc" />
<path
style="fill:none;stroke:#0081d5;stroke-width:0.3;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:2.4, 0.3;stroke-dashoffset:0;stroke-opacity:1"
d="m 71.561356,179.69463 -5.224783,0.0131"
id="path23791-7"
inkscape:connector-curvature="0"
sodipodi:nodetypes="cc" />
<path
style="fill:none;stroke:#0081d5;stroke-width:0.3;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:2.4, 0.3;stroke-dashoffset:0;stroke-opacity:1"
d="m 71.51701,176.88556 -5.224783,0.0131"
id="path23791-7-3"
inkscape:connector-curvature="0"
sodipodi:nodetypes="cc" />
<text
xml:space="preserve"
style="font-style:normal;font-weight:normal;font-size:7.5037px;line-height:1.25;font-family:sans-serif;letter-spacing:0px;word-spacing:0px;fill:#0081d5;fill-opacity:1;stroke:none;stroke-width:0.187593"
x="71.381172"
y="189.32043"
id="text21059-5"><tspan
sodipodi:role="line"
id="tspan21057-6"
x="71.381172"
y="189.32043"
style="fill:#0081d5;fill-opacity:1;stroke-width:0.187593">W</tspan></text>
<text
xml:space="preserve"
style="font-style:normal;font-weight:normal;font-size:7.5037px;line-height:1.25;font-family:sans-serif;letter-spacing:0px;word-spacing:0px;fill:#0081d5;fill-opacity:1;stroke:none;stroke-width:0.187593"
x="84.089783"
y="188.25977"
id="text21059-5-7"><tspan
sodipodi:role="line"
id="tspan21057-6-1"
x="84.089783"
y="188.25977"
style="fill:#0081d5;fill-opacity:1;stroke-width:0.187593">S</tspan></text>
<path
style="fill:none;stroke:#0081d5;stroke-width:0.3;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:2.4, 0.3;stroke-dashoffset:0;stroke-opacity:1"
d="m 71.648638,179.5799 -0.0097,2.66362"
id="path23791-7-9"
inkscape:connector-curvature="0"
sodipodi:nodetypes="cc" />
<path
style="fill:none;stroke:#0081d5;stroke-width:0.3;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:2.4, 0.3;stroke-dashoffset:0;stroke-opacity:1"
d="m 78.468682,179.60109 -0.0097,2.61685"
id="path23791-7-9-3"
inkscape:connector-curvature="0"
sodipodi:nodetypes="cc" />
<path
style="fill:none;stroke:#0081d5;stroke-width:0.3;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:2.4, 0.3;stroke-dashoffset:0;stroke-opacity:1"
d="m 94.848919,179.80535 -0.0097,2.61685"
id="path23791-7-9-3-1"
inkscape:connector-curvature="0"
sodipodi:nodetypes="cc" />
<path
style="fill:none;stroke:#0081d5;stroke-width:0.25;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1;marker-start:url(#TriangleInL-74);marker-end:url(#marker23801-54)"
d="m 76.876847,181.51957 -3.624842,-0.0298"
id="path23791-43"
inkscape:connector-curvature="0"
sodipodi:nodetypes="cc" />
<text
xml:space="preserve"
style="font-style:normal;font-weight:normal;font-size:10.5833px;line-height:1.25;font-family:sans-serif;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.264583"
x="58.652298"
y="173.61502"
id="text15381" />
</g>
<g
inkscape:groupmode="layer"
id="layer7"
inkscape:label="Layer 2"
transform="translate(-50.901726,-151.02664)">
<rect
style="opacity:1;fill:#fcb23c;fill-opacity:1;stroke:#895502;stroke-width:0.499178;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
id="rect20424"
width="6.6496596"
height="2.6584671"
x="71.743835"
y="176.97217" />
<path
style="fill:none;stroke:#474747;stroke-width:0.5;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:3, 0.5;stroke-dashoffset:0;stroke-opacity:1"
d="m 101.6132,176.95663 9.62485,-9.8911"
id="path20538-6-8-8"
inkscape:connector-curvature="0"
inkscape:transform-center-x="0.65481035"
inkscape:transform-center-y="7.4835468"
sodipodi:nodetypes="cc" />
<path
style="fill:none;stroke:#474747;stroke-width:0.5;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:3, 0.5;stroke-dashoffset:0;stroke-opacity:1"
d="m 101.98778,179.66243 9.62485,-9.8911"
id="path20538-6-8-8-4"
inkscape:connector-curvature="0"
inkscape:transform-center-x="0.65481035"
inkscape:transform-center-y="7.4835468"
sodipodi:nodetypes="cc" />
<path
style="fill:none;stroke:#474747;stroke-width:0.5;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:3, 0.5;stroke-dashoffset:0;stroke-opacity:1"
d="m 94.925946,176.78926 9.624824,-9.8911"
id="path20538-6-8-0-3-0"
inkscape:connector-curvature="0"
inkscape:transform-center-x="0.65481035"
inkscape:transform-center-y="7.4835468"
sodipodi:nodetypes="cc" />
<rect
style="fill:#fcb23c;fill-opacity:1;stroke:#895502;stroke-width:0.499178;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
id="rect20424-4"
width="6.6496596"
height="2.6584671"
x="94.909355"
y="176.92873" />
<path
style="fill:none;stroke:#0081d5;stroke-width:0.3;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1;marker-end:url(#TriangleOutL)"
d="m 68.396624,187.21173 v -5.41497"
id="path21071"
inkscape:connector-curvature="0"
sodipodi:nodetypes="cc" />
<path
style="fill:none;stroke:#0081d5;stroke-width:0.3;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1;marker-end:url(#TriangleOutL-9)"
d="m 68.307853,169.42208 v 5.41497"
id="path21071-8"
inkscape:connector-curvature="0"
sodipodi:nodetypes="cc" />
</g>
</svg>

After

Width:  |  Height:  |  Size: 32 KiB