Commit a43aaa9c authored by natsfr's avatar natsfr

merge

parent 562a9d99
This diff is collapsed.
! Filename: BFR93AD.S2P Version: 2.0
! NXP part #: BFR93A Date: May 1990
! Bias condition: Vce=5V, Ic=30mA
!
# MHz S MA R 50
! Freq S11 S21 S12 S22 !GUM [dB]
40 .499 -44.2 42.811 149.9 .011 74.3 .853 -23.4 ! 39.5
100 .406 -88.8 28.622 124.9 .023 62.9 .606 -41.3 ! 31.9
200 .369 -127.6 17.097 107.9 .035 64.2 .392 -49.9 ! 26.0
300 .359 -144.5 11.934 99.3 .045 66.9 .301 -51.1 ! 22.5
400 .348 -153.5 9.173 94.3 .057 68.3 .257 -51.5 ! 20.1
500 .367 -160.2 7.512 89.4 .070 70.5 .232 -50.9 ! 18.4
600 .367 -167.0 6.297 86.7 .081 70.8 .218 -50.7 ! 16.8
700 .341 -168.3 5.464 83.7 .093 72.8 .210 -50.7 ! 15.5
800 .361 -175.7 4.781 81.3 .105 72.0 .207 -49.9 ! 14.4
900 .348 -177.4 4.317 78.8 .117 72.3 .204 -50.4 ! 13.4
1000 .349 176.8 3.861 76.0 .128 72.3 .198 -49.9 ! 12.5
1200 .352 173.4 3.286 71.2 .152 71.5 .189 -50.8 ! 11.1
1400 .371 168.3 2.852 66.7 .174 70.2 .182 -53.4 ! 9.9
1600 .358 166.1 2.548 63.4 .198 69.2 .183 -54.4 ! 8.9
1800 .345 158.4 2.273 59.3 .220 68.0 .185 -56.0 ! 7.8
2000 .352 154.7 2.126 56.0 .242 66.5 .175 -56.0 ! 7.3
2200 .367 147.1 1.932 52.6 .264 66.2 .152 -58.2 ! 6.4
2400 .390 148.6 1.810 49.5 .288 64.1 .141 -67.2 ! 6.0
2600 .391 146.3 1.694 46.1 .307 62.5 .142 -74.4 ! 5.4
2800 .388 142.6 1.628 43.3 .329 61.4 .142 -78.4 ! 5.0
3000 .407 136.2 1.537 40.6 .352 59.2 .129 -80.1 ! 4.6
\ No newline at end of file
......@@ -13,77 +13,120 @@ import sys
import math
import cmath
''' Open S2P Files and extract data '''
def parse_spar(file, freq):
f = open(file, "r")
tmpspars = []
for line in f:
tmpspars.append(line.strip().split())
class TransistorBlock:
spars = {}#[] # 1: Freq 2: S11 3: S21 4: S12 5: S22
for l in tmpspars:
if(l[0] != "!" and l[0] != "#"):
tmp = []
#tmp.append(float(l[0])) # FREQ
tmp.append(complex(float(l[1]), float(l[2]))) # S11
tmp.append(complex(float(l[3]), float(l[4]))) # S21
tmp.append(complex(float(l[5]), float(l[6]))) # S12
tmp.append(complex(float(l[7]), float(l[8]))) # S22
#spars.append(tmp)
spars[float(l[0])] = tmp
return spars
''' Calculate John Rollett stability factor '''
def calc_stab(Ds, S):
K = (1 + cmath.polar(Ds)[0] ** 2 - cmath.polar(S[11])[0] ** 2 - \
cmath.polar(S[22])[0] ** 2) / (2 * cmath.polar(S[21])[0] * cmath.polar(S[12])[0])
return K
def __init__(self, file, freq, config):
self.freq = freq
self.config = config
self.spformats = {}
self.parse_spar(file,freq)
''' Caculate Maximum Available Gain '''
def calc_mag(Ds, S, K):
B1 = 1 + cmath.polar(S[11])[0] ** 2 - cmath.polar(S[22])[0] ** 2 - cmath.polar(Ds)[0] ** 2
''' Open S2P Files and extract data '''
def parse_spar(self, file, freq):
f = open(file, "r")
tmpspars = []
for line in f:
if line.startswith("#"):
sfor = line.strip().split()
self.spformats["UNIT"] = sfor[1]
self.spformats["TYPE"] = sfor[2]
self.spformats["FORMAT"] = sfor[3]
# Apparently the nominal Impedance is splitted: R 50
self.spformats["R"] = sfor[5]
elif not line.startswith("!"):
tmpspars.append(line.strip().split())
# Parse options: we mainly need to know unit and complex format
# http://cp.literature.agilent.com/litweb/pdf/genesys200801/sim/linear_sim/sparams/touchstone_file_format.htms
self.spars = {}# 1: Freq 2: S11 3: S21 4: S12 5: S22
for l in tmpspars:
if(l[0] != "!" and l[0] != "#"):
tmp = []
if self.spformats["FORMAT"] == "RI" : # Real Imaginary
tmp.append(complex(float(l[1]), float(l[2]))) # S11
tmp.append(complex(float(l[3]), float(l[4]))) # S21
tmp.append(complex(float(l[5]), float(l[6]))) # S12
tmp.append(complex(float(l[7]), float(l[8]))) # S22
elif self.spformats["FORMAT"] == "MA" : # Magnitude Angle
tmp.append(cmath.rect(float(l[1]), float(l[2]))) # S11
tmp.append(cmath.rect(float(l[3]), float(l[4]))) # S21
tmp.append(cmath.rect(float(l[5]), float(l[6]))) # S12
tmp.append(cmath.rect(float(l[7]), float(l[8]))) # S22
else :
print("Unsupported Number Format: %s" % self.spformats["FORMAT"])
exit(-1)
# We always set freq to MHz
freq = float(l[0])
if self.spformats["UNIT"] == "GHz":
freq = freq * 1000
elif self.spformats["UNIT"] == "KHz":
freq = freq / 1000
elif self.spformats["UNIT"] == "Hz":
freq = freq / 1000000
self.spars[freq] = tmp
''' Calculate John Rollett stability factor '''
def calc_stab(self):
S = self.S
self.K = (1 + cmath.polar(self.Ds)[0] ** 2 - cmath.polar(S[11])[0] ** 2 - \
cmath.polar(S[22])[0] ** 2) / (2 * cmath.polar(S[21])[0] * cmath.polar(S[12])[0])
''' Caculate Maximum Available Gain '''
def calc_mag(self):
S = self.S
self.B1 = 1 + cmath.polar(S[11])[0] ** 2 - cmath.polar(S[22])[0] ** 2 - cmath.polar(self.Ds)[0] ** 2
ksq = 0.0
if B1 < 0 :
ksq = math.sqrt(K**2 - 1)
else :
ksq = math.sqrt(k**2 - 1) * -1
ksq = 0.0
if self.B1 < 0 :
ksq = math.sqrt(self.K**2 - 1)
else :
ksq = math.sqrt(self.K**2 - 1) * -1
self.MAG = 10 * math.log(cmath.polar(S[11])[0] / cmath.polar(S[12])[0]) + \
10 * math.log(self.K + ksq)
MAG = 10 * math.log(cmath.polar(S[11])[0] / cmath.polar(S[12])[0]) + \
10 * math.log(K + ksq)
''' Calculate Maximum Unilateral Gain (S12 = 0)'''
def calc_gum(self):
S = self.S
self.GUM = 10 * math.log(cmath.polar(S[21])[0]**2 / ((1-cmath.polar(S[11])[0]**2)*(1-cmath.polar(S[22])[0]**2)))
return MAG
def calc_value(freq, spars, config):
sparam = spars[freq]
S = {}
S[11] = sparam[0]
S[21] = sparam[1]
S[12] = sparam[2]
S[22] = sparam[3]
def set_freq(self, freq):
self.freq = freq
Ds = S[11] * S[22] - S[12] * S[21]
K = calc_stab(Ds, S)
def calc_stability_mag(self):
self.sparam = self.spars[self.freq]
self.S = {}
self.S[11] = self.sparam[0]
self.S[21] = self.sparam[1]
self.S[12] = self.sparam[2]
self.S[22] = self.sparam[3]
S = self.S
self.Ds = S[11] * S[22] - S[12] * S[21]
self.calc_stab()
if self.K < 1 :
print("Warning ! K factor %f < 1.0 , amplifier could be unstable" % self.K)
print("Undefined Maximum Available Gain")
else :
print("Stable amplifier design. K factor %f >= 1" % self.K)
self.calc_mag()
print("Maximum Available Gain: %fdB" % self.MAG)
def calc_scm(self):
S = self.S
if self.K > 1 :
self.C1 = S[11] - (self.Ds * complex.conjugate(S[22]))
self.C2 = S[22] - (self.Ds * complex.conjugate(S[11]))
# B1 is already calculated for MAG
self.B2 = 1 - cmath.polar(S[11])[0] ** 2 - cmath.polar(S[22])[0] ** 2 - cmath.polar(self.Ds)[0] ** 2
else :
print("Can't calculate SCM, K < 1, try lossy match")
if K < 1 :
print("Warning ! K factor %f < 1.0 , amplifier could be unstable" % K)
print("Undefined Maximum Available Gain")
else :
print("Stable amplifier design. K factor %f >= 1" % K)
MAG = calc_mag(Ds, S, K)
print("Maximum Available Gain: %fdB" % MAG)
#Select the kind of configuration for the amplifier
if config == 'SCM' :
# Simultaneous Conjugate Match
print("Simulaneous Conjugate Match")
elif config == 'ONF' :
# Optimum Noise Figure
print("Not yet available")
else :
print("Unknown mode")
if __name__ == '__main__':
if(len(sys.argv) < 4):
print("Error: usage\nauto_match.py spar_file.s2p frequency configuration\n")
......@@ -91,6 +134,7 @@ if __name__ == '__main__':
fname = sys.argv[1]
freq = float(sys.argv[2])
config = sys.argv[3]
spars = parse_spar(fname, freq)
calc_value(freq, spars, config)
\ No newline at end of file
q1 = TransistorBlock(fname, freq, config)
q1.calc_stability_mag()
q1.calc_gum()
print("GUM: %fdB" % q1.GUM)
......@@ -8,11 +8,14 @@ WIRE 48 0 48 -48
WIRE 240 0 240 -48
WIRE -480 48 -480 -32
WIRE 1360 96 1360 64
WIRE 1632 96 1360 96
WIRE 1520 96 1360 96
WIRE 1632 96 1520 96
WIRE 2400 96 2400 64
WIRE 2672 96 2400 96
WIRE 2592 96 2400 96
WIRE 2672 96 2592 96
WIRE 240 112 240 80
WIRE 528 112 240 112
WIRE 416 112 240 112
WIRE 528 112 416 112
WIRE 240 128 240 112
WIRE 1360 128 1360 96
WIRE 2400 128 2400 96
......@@ -30,8 +33,6 @@ WIRE 2000 176 1904 176
WIRE 2144 176 2144 64
WIRE 2144 176 2064 176
WIRE 2336 176 2144 176
WIRE 1632 192 1632 96
WIRE 2672 192 2672 96
WIRE -176 224 -176 176
WIRE 240 240 240 224
WIRE 352 240 240 240
......@@ -64,11 +65,9 @@ WIRE 2496 384 2400 384
WIRE 864 400 864 336
WIRE 1104 400 1104 352
WIRE 1360 400 1360 384
WIRE 1632 400 1632 272
WIRE 1904 400 1904 336
WIRE 2144 400 2144 352
WIRE 2400 400 2400 384
WIRE 2672 400 2672 272
WIRE -176 416 -176 304
WIRE 48 416 48 352
WIRE 240 416 240 384
......@@ -81,16 +80,17 @@ FLAG 48 -48 3.3v
FLAG 240 -48 3.3v
FLAG 1360 400 0
FLAG 1104 400 0
FLAG 1632 400 0
FLAG 864 400 0
FLAG 1104 -64 3.3v
FLAG 1360 -64 3.3v
FLAG 2400 400 0
FLAG 2144 400 0
FLAG 2672 400 0
FLAG 1904 400 0
FLAG 2144 -64 3.3v
FLAG 2400 -64 3.3v
FLAG 2592 96 BFR93A
FLAG 1520 96 PRF347
FLAG 416 112 2N2222
SYMBOL npn 176 128 R0
SYMATTR InstName Q1
SYMATTR Value 2N2222
......@@ -136,9 +136,6 @@ SYMATTR Prefix X
SYMBOL res 1344 256 R0
SYMATTR InstName R6
SYMATTR Value 100
SYMBOL res 1616 176 R0
SYMATTR InstName R7
SYMATTR Value 1k
SYMBOL res 1344 -32 R0
SYMATTR InstName R8
SYMATTR Value 115
......@@ -156,9 +153,9 @@ SYMATTR Value 10
SYMBOL voltage 864 240 R0
WINDOW 123 24 124 Left 2
WINDOW 39 0 0 Left 2
SYMATTR Value2 AC 1 1
SYMATTR InstName V3
SYMATTR Value SINE(0 0.1 1g)
SYMATTR Value2 AC 1 1
SYMBOL cap 1440 288 R0
SYMATTR InstName C4
SYMATTR Value 50p
......@@ -169,9 +166,6 @@ SYMATTR Prefix X
SYMBOL res 2384 256 R0
SYMATTR InstName R11
SYMATTR Value 100
SYMBOL res 2656 176 R0
SYMATTR InstName R12
SYMATTR Value 1k
SYMBOL res 2384 -32 R0
SYMATTR InstName R13
SYMATTR Value 115
......@@ -189,12 +183,12 @@ SYMATTR Value 10
SYMBOL voltage 1904 240 R0
WINDOW 123 24 124 Left 2
WINDOW 39 0 0 Left 2
SYMATTR Value2 AC 1 1
SYMATTR InstName V4
SYMATTR Value SINE(0 0.1 1g)
SYMATTR Value2 AC 1 1
SYMBOL cap 2480 288 R0
SYMATTR InstName C6
SYMATTR Value 50p
TEXT -512 440 Left 2 !.tran 1
TEXT -512 440 Left 2 !.ac oct 1000 1 10g
TEXT -512 528 Left 2 !.INCLUDE PRF947_nxp.lib
TEXT -512 568 Left 2 !.INCLUDE BFR93A_nxp.lib
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment