mirror of
https://gitlab.com/kicad/code/kicad.git
synced 2025-09-14 02:03:12 +02:00
173 lines
8.0 KiB
C++
173 lines
8.0 KiB
C++
/*
|
|
* 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;
|
|
}
|