/* * twistedpair.h - twisted pair class definition * * Copyright (C) 2011 Michael Margraf * Modifications 2011 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 TWISTEDPAIR::TWISTEDPAIR() : TRANSLINE() { m_Name = "TwistedPair"; // Initialize these variables mainly to avoid warnings from a static analyzer din = 0.0; // Inner diameter of conductor dout = 0.0; // Outer diameter of insulator twists = 0.0; // Twists per length er_env = 0.0; // dielectric constant of environment*/ len = 0.0; // Length of cable Z0 = 0.0; // characteristic impedance ang_l = 0.0; // Electrical length in angle atten_dielectric = 0.0; // Loss in dielectric (dB) atten_cond = 0.0; // Loss in conductors (dB) er_eff = 1.0; // Effective dielectric constant } // ------------------------------------------------------------------- void TWISTEDPAIR::getProperties() { m_freq = getProperty( FREQUENCY_PRM ); din = getProperty( PHYS_DIAM_IN_PRM ); dout = getProperty( PHYS_DIAM_OUT_PRM ); len = getProperty( PHYS_LEN_PRM ); er = getProperty( EPSILONR_PRM ); m_murC = getProperty( MURC_PRM ); m_tand = getProperty( TAND_PRM ); m_sigma = 1.0 / getProperty( RHO_PRM ); twists = getProperty( TWISTEDPAIR_TWIST_PRM ); er_env = getProperty( TWISTEDPAIR_EPSILONR_ENV_PRM ); Z0 = getProperty( Z0_PRM ); ang_l = getProperty( ANG_L_PRM ); } // ------------------------------------------------------------------- void TWISTEDPAIR::calc() { m_skindepth = skin_depth(); double tw = atan( twists * M_PI * dout ); // pitch angle er_eff = er_env + (0.25 + 0.0007 * tw * tw) * (er - er_env); Z0 = ZF0 / M_PI / sqrt( er_eff ) * acosh( dout / din ); atten_cond = 10.0 / log( 10.0 ) * len / m_skindepth / m_sigma / M_PI / Z0 / (din - m_skindepth); atten_dielectric = 20.0 / log( 10.0 ) * len * M_PI / C0* m_freq * sqrt( er_eff ) * m_tand; ang_l = 2.0* M_PI* len* sqrt( er_eff ) * m_freq / C0; // in radians } // ------------------------------------------------------------------- void TWISTEDPAIR::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 TWISTEDPAIR::analyze() { getProperties(); calc(); show_results(); } #define MAX_ERROR 0.000001 // ------------------------------------------------------------------- void TWISTEDPAIR::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++; if( isSelected( PHYS_DIAM_IN_PRM ) ) { increment = din / 100.0; din += increment; } else { increment = dout / 100.0; dout += 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; if( isSelected( PHYS_DIAM_IN_PRM ) ) din += slope; else dout += slope; if( din <= 0.0 ) din = increment; if( dout <= 0.0 ) dout = increment; /* find new error */ /* compute parameters */ calc(); Z0_current = Z0; error = fabs( Z0_dest - Z0_current ); if( iteration > 100 ) break; } setProperty( PHYS_DIAM_IN_PRM, din ); setProperty( PHYS_DIAM_OUT_PRM, dout ); /* 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(); }