/* * stripline.cpp - stripline class definition * * Copyright (C) 2011 Michael Margraf * Modifications 2018 for Kicad: Jean-Pierre Charras * * 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 #include #include #include #include #include #include STRIPLINE::STRIPLINE() : TRANSLINE() { m_Name = "StripLine"; // Initialize these variables mainly to avoid warnings from a static analyzer 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) } // ------------------------------------------------------------------- void STRIPLINE::getProperties() { m_freq = getProperty( FREQUENCY_PRM ); 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 ); m_murC = getProperty( MURC_PRM ); m_tand = getProperty( TAND_PRM ); m_sigma = 1.0 / getProperty( RHO_PRM ); 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; ac = sqrt( m_freq / m_sigma / 17.2 ); 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() { m_skindepth = skin_depth(); 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); atten_dielectric = 20.0 / log( 10.0 ) * len * (M_PI / C0) * m_freq * sqrt( er ) * m_tand; ang_l = 2.0* M_PI* len* sqrt( er ) * m_freq / C0; // in radians } // ------------------------------------------------------------------- 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" ); setResult( 3, m_skindepth / UNIT_MICRON, "µm" ); } // ------------------------------------------------------------------- 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 ); len = C0 / m_freq / sqrt( er_eff ) * ang_l / 2.0 / M_PI; /* in m */ setProperty( PHYS_LEN_PRM, len ); /* compute parameters */ calc(); /* print results in the subwindow */ show_results(); }