174 lines
4.7 KiB
C++
174 lines
4.7 KiB
C++
/*
|
||
* twistedpair.h - twisted pair class definition
|
||
*
|
||
* Copyright (C) 2011 Michael Margraf <michael.margraf@alumni.tu-berlin.de>
|
||
* 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 <stdlib.h>
|
||
#include <stdio.h>
|
||
#include <string.h>
|
||
#include <math.h>
|
||
|
||
#include <units.h>
|
||
#include <transline.h>
|
||
#include <twistedpair.h>
|
||
|
||
TWISTEDPAIR::TWISTEDPAIR() : TRANSLINE()
|
||
{
|
||
m_name = "TwistedPair";
|
||
}
|
||
|
||
|
||
// -------------------------------------------------------------------
|
||
void TWISTEDPAIR::getProperties()
|
||
{
|
||
f = getProperty( FREQUENCY_PRM );
|
||
din = getProperty( PHYS_DIAM_IN_PRM );
|
||
dout = getProperty( PHYS_DIAM_OUT_PRM );
|
||
len = getProperty( PHYS_LEN_PRM );
|
||
|
||
er = getProperty( EPSILONR_PRM );
|
||
murC = getProperty( MURC_PRM );
|
||
tand = getProperty( TAND_PRM );
|
||
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()
|
||
{
|
||
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 / skindepth / sigma / M_PI / Z0 / (din - skindepth);
|
||
|
||
atten_dielectric = 20.0 / log( 10.0 ) * len * M_PI / C0* f* sqrt( er_eff ) * tand;
|
||
|
||
ang_l = 2.0* M_PI* len* sqrt( er_eff ) * f / 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, skindepth / UNIT_MICRON, "<EFBFBD>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 / f / 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();
|
||
}
|