2011-08-05 19:53:42 +00:00
|
|
|
/*
|
|
|
|
* stripline.cpp - stripline class definition
|
|
|
|
*
|
|
|
|
* Copyright (C) 2011 Michael Margraf <michael.margraf@alumni.tu-berlin.de>
|
2018-06-07 13:44:20 +00:00
|
|
|
* Modifications 2018 for Kicad: Jean-Pierre Charras
|
2011-08-05 19:53:42 +00:00
|
|
|
*
|
|
|
|
* 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.
|
|
|
|
*
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
2012-09-21 17:02:54 +00:00
|
|
|
#include <cmath>
|
2019-12-05 14:03:15 +00:00
|
|
|
#include <cstdio>
|
|
|
|
#include <cstdlib>
|
|
|
|
#include <cstring>
|
2011-08-05 19:53:42 +00:00
|
|
|
|
2012-01-23 04:33:36 +00:00
|
|
|
#include <units.h>
|
|
|
|
#include <transline.h>
|
|
|
|
#include <stripline.h>
|
2011-08-05 19:53:42 +00:00
|
|
|
|
|
|
|
STRIPLINE::STRIPLINE() : TRANSLINE()
|
|
|
|
{
|
2018-06-07 13:44:20 +00:00
|
|
|
m_Name = "StripLine";
|
2015-03-04 09:26:00 +00:00
|
|
|
|
|
|
|
// Initialize these variables mainly to avoid warnings from a static analyzer
|
2015-03-11 13:59:43 +00:00
|
|
|
h = 0.0; // height of substrate
|
|
|
|
a = 0.0; // distance of strip to top metal
|
|
|
|
t = 0.0; // thickness of top metal
|
|
|
|
w = 0.0; // width of line
|
|
|
|
len = 0.0; // length of line
|
|
|
|
Z0 = 0.0; // characteristic impedance
|
|
|
|
ang_l = 0.0; // Electrical length in angle
|
|
|
|
er_eff = 0.0; // effective dielectric constant
|
|
|
|
atten_dielectric = 0.0; // Loss in dielectric (dB)
|
|
|
|
atten_cond = 0.0; // Loss in conductors (dB)
|
2011-08-05 19:53:42 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// -------------------------------------------------------------------
|
|
|
|
void STRIPLINE::getProperties()
|
|
|
|
{
|
2018-06-07 13:18:56 +00:00
|
|
|
m_freq = getProperty( FREQUENCY_PRM );
|
2011-08-05 19:53:42 +00:00
|
|
|
w = getProperty( PHYS_WIDTH_PRM );
|
|
|
|
len = getProperty( PHYS_LEN_PRM );
|
|
|
|
h = getProperty( H_PRM);
|
|
|
|
a = getProperty( STRIPLINE_A_PRM );
|
|
|
|
t = getProperty( T_PRM );
|
|
|
|
|
|
|
|
er = getProperty( EPSILONR_PRM );
|
2018-06-07 13:34:13 +00:00
|
|
|
m_murC = getProperty( MURC_PRM );
|
2018-06-07 13:44:20 +00:00
|
|
|
m_tand = getProperty( TAND_PRM );
|
2018-06-07 13:30:35 +00:00
|
|
|
m_sigma = 1.0 / getProperty( RHO_PRM );
|
2011-08-05 19:53:42 +00:00
|
|
|
Z0 = getProperty( Z0_PRM );
|
|
|
|
ang_l = getProperty( ANG_L_PRM );
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// -------------------------------------------------------------------
|
|
|
|
// calculate characteristic impedance and conductor loss
|
|
|
|
double STRIPLINE::lineImpedance( double height, double& ac )
|
|
|
|
{
|
|
|
|
double ZL;
|
|
|
|
double hmt = height - t;
|
|
|
|
|
2018-06-07 13:30:35 +00:00
|
|
|
ac = sqrt( m_freq / m_sigma / 17.2 );
|
2011-08-05 19:53:42 +00:00
|
|
|
if( w / hmt >= 0.35 )
|
|
|
|
{
|
|
|
|
ZL = w +
|
|
|
|
( 2.0 * height *
|
|
|
|
log( (2.0 * height - t) / hmt ) - t * log( height * height / hmt / hmt - 1.0 ) ) / M_PI;
|
|
|
|
ZL = ZF0 * hmt / sqrt( er ) / 4.0 / ZL;
|
|
|
|
|
|
|
|
ac *= 2.02e-6 * er * ZL / hmt;
|
|
|
|
ac *= 1.0 + 2.0 * w / hmt + (height + t) / hmt / M_PI* log( 2.0 * height / t - 1.0 );
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
double tdw = t / w;
|
|
|
|
if( t / w > 1.0 )
|
|
|
|
tdw = w / t;
|
|
|
|
double de = 1.0 + tdw / M_PI * ( 1.0 + log( 4.0 * M_PI / tdw ) ) + 0.236 * pow( tdw, 1.65 );
|
|
|
|
if( t / w > 1.0 )
|
|
|
|
de *= t / 2.0;
|
|
|
|
else
|
|
|
|
de *= w / 2.0;
|
|
|
|
ZL = ZF0 / 2.0 / M_PI / sqrt( er ) * 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;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// -------------------------------------------------------------------
|
|
|
|
void STRIPLINE::calc()
|
|
|
|
{
|
2018-06-07 13:30:35 +00:00
|
|
|
m_skindepth = skin_depth();
|
2011-08-05 19:53:42 +00:00
|
|
|
|
|
|
|
er_eff = er; // no dispersion
|
|
|
|
|
|
|
|
double ac1, ac2;
|
|
|
|
Z0 = 2.0 /
|
|
|
|
( 1.0 / lineImpedance( 2.0 * a + t, ac1 ) + 1.0 / lineImpedance( 2.0 * (h - a) - t, ac2 ) );
|
|
|
|
|
|
|
|
atten_cond = len * 0.5 * (ac1 + ac2);
|
2018-06-07 13:44:20 +00:00
|
|
|
atten_dielectric = 20.0 / log( 10.0 ) * len * (M_PI / C0) * m_freq * sqrt( er ) * m_tand;
|
2011-08-05 19:53:42 +00:00
|
|
|
|
2018-06-07 13:18:56 +00:00
|
|
|
ang_l = 2.0* M_PI* len* sqrt( er ) * m_freq / C0; // in radians
|
2011-08-05 19:53:42 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// -------------------------------------------------------------------
|
|
|
|
void STRIPLINE::show_results()
|
|
|
|
{
|
|
|
|
setProperty( Z0_PRM, Z0 );
|
|
|
|
setProperty( ANG_L_PRM, ang_l );
|
|
|
|
|
|
|
|
setResult( 0, er_eff, "" );
|
|
|
|
setResult( 1, atten_cond, "dB" );
|
|
|
|
setResult( 2, atten_dielectric, "dB" );
|
|
|
|
|
2018-06-07 13:30:35 +00:00
|
|
|
setResult( 3, m_skindepth / UNIT_MICRON, "µm" );
|
2011-08-05 19:53:42 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// -------------------------------------------------------------------
|
|
|
|
void STRIPLINE::analyze()
|
|
|
|
{
|
|
|
|
getProperties();
|
|
|
|
calc();
|
|
|
|
show_results();
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
#define MAX_ERROR 0.000001
|
|
|
|
|
|
|
|
// -------------------------------------------------------------------
|
|
|
|
void STRIPLINE::synthesize()
|
|
|
|
{
|
|
|
|
double Z0_dest, Z0_current, Z0_result, increment, slope, error;
|
|
|
|
int iteration;
|
|
|
|
|
|
|
|
getProperties();
|
|
|
|
|
|
|
|
/* required value of Z0 */
|
|
|
|
Z0_dest = Z0;
|
|
|
|
|
|
|
|
/* Newton's method */
|
|
|
|
iteration = 0;
|
|
|
|
|
|
|
|
/* compute parameters */
|
|
|
|
calc();
|
|
|
|
Z0_current = Z0;
|
|
|
|
|
|
|
|
error = fabs( Z0_dest - Z0_current );
|
|
|
|
|
|
|
|
while( error > MAX_ERROR )
|
|
|
|
{
|
|
|
|
iteration++;
|
|
|
|
increment = w / 100.0;
|
|
|
|
w += increment;
|
|
|
|
/* compute parameters */
|
|
|
|
calc();
|
|
|
|
Z0_result = Z0;
|
|
|
|
/* 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)) */
|
|
|
|
slope = (Z0_result - Z0_current) / increment;
|
|
|
|
slope = (Z0_dest - Z0_current) / slope - increment;
|
|
|
|
w += slope;
|
|
|
|
if( w <= 0.0 )
|
|
|
|
w = increment;
|
|
|
|
/* find new error */
|
|
|
|
/* compute parameters */
|
|
|
|
calc();
|
|
|
|
Z0_current = Z0;
|
|
|
|
error = fabs( Z0_dest - Z0_current );
|
|
|
|
if( iteration > 100 )
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
setProperty( PHYS_WIDTH_PRM, w );
|
|
|
|
/* calculate physical length */
|
|
|
|
ang_l = getProperty( ANG_L_PRM );
|
2018-06-07 13:18:56 +00:00
|
|
|
len = C0 / m_freq / sqrt( er_eff ) * ang_l / 2.0 / M_PI; /* in m */
|
2011-08-05 19:53:42 +00:00
|
|
|
setProperty( PHYS_LEN_PRM, len );
|
|
|
|
|
|
|
|
/* compute parameters */
|
|
|
|
calc();
|
|
|
|
|
|
|
|
/* print results in the subwindow */
|
|
|
|
show_results();
|
|
|
|
}
|