home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
HAM Radio 1
/
HamRadio.cdr
/
tech
/
rf4
/
mxfilter.pas
< prev
next >
Wrap
Pascal/Delphi Source File
|
1986-06-11
|
21KB
|
593 lines
program maxfilter; { Program Maximizes Possible Ripple Frequencies }
{ While Maintaining Required Attenuation Values }
{ Specified in Stop Band }
{ Jeff Crawford TRW February 14, 1985 }
{ StopBand Requirements Are Specified by Operator. This Program Calculates }
{ if The Difference Between That Obtainable [ Using Chebycheff Approx.] and }
{ That Required is > 0 At All Specified StopBand Frequencies. If This }
{ Margin is Not > 0 Then a Higher Order Filter is Required. If the Margin is}
{ > 0 the StopBand Frequency at Which the Smallest Margin Exists is }
{ Determined by a Simple Search. First, Using the Previously Given Upper }
{ Ripple Frequency, Linear Interpolation of the [Loss Function - Required Att}
{ is Used to Move Out the Lower Ripple Frequency to a Point Where the }
{ Equation Above is Identically Zero. A New Geometric Center Frequency is }
{ Calculated. Another Determination of Which Upper StopBand Frequency Has }
{ the Least Margin With the Newly Calculated Lower wp is Made. Linear }
{ Interpolation of the Upper StopBand Frequency is Done With the Previously }
{ Calculated New Lower Ripple Frequency, wp_lo. This Entire Procedure is }
{ Continued Until Convergence. }
{ REFERENCES }
{ [1] "Dissipation Loss of Chebyshev BandPass Filters", Harold Schumacher, }
{ Microwave Journal, pp 41-43, August, 1977. }
{ [2] " Microwave Filters, Impedance Matching Networks, and Coupling }
{ Structures", G.L. Matthaei, Leo Young, E. M. T. Jones, McGraw Hill }
{ Book Company, 1964. }
{ [3] "Principles of Active Network Synthesis and Design", Gobind Daryanani}
{ John Wiley & Sons, 1976. }
type matrix_a = array[1..16] of real;
var wp_lo_max,wp_hi_min : real; { Lower, Upper Ripple Freqs; Begin }
wp_lo,wp_hi : real; { Iterated New Ripple Freqs }
eta,L_db : real; { dB Ripple in }
N_lo,N_hi : integer; { # Requirements in Stop-Bands }
i,j,ii : integer; { Loop Counters }
Freq : matrix_a; { Frequencies in Stop-Bands }
Att : matrix_a; { Attenuations in Stop-Bands }
delta_Db : matrix_a; { Differences in Attenuation }
{ & That Specified as Needed }
del : real;
order : integer; { Filter Order }
wp : real; { Ripple Frequency in Iterration }
wp_new : real; { Newly Solved for Ripple Freq }
Flag1 : boolean; { Determines if Delta-dB < 0 }
ord_lo,ord_hi : integer; { Lower, Up }
No,Num_lo,Num_hi : integer; { Freq of Minimum Attenuation }
min : real; { Minimum Attenuation in StopBand }
wp_new_1,wp_new_2 : real; { New wp Frequencies }
wo_geom : real; { Geometric Center Frequency }
temp : real; { Temporary Holding Variable }
stat : real; { Aborts Loop Upon Convergence }
wp_lo_save,wp_hi_save : real; { wp's From Previous Iteration }
freq_margin : real; { Percentage Error Allowed in Calc }
{ When Exceeded, Leaves Loop }
stat_ptr : string[1]; { Printer Status }
IL : real; { Center of Band Insertion Loss }
Qu : real; { Unloaded Resonator Q }
inkey :char;
Function Log10( X:Real ):Real;
begin
Log10:=0.434294482*Ln( X );
end;
{///////////////////////////////////////////////}
Function Cosh( X:Real ):Real;
var temp : Real;
begin
temp:=exp( X );
Cosh:= 0.5 * ( temp + 1/temp );
end;
{///////////////////////////////////////////////}
Function Sinh( X: real): real;
var temp: real;
begin
temp:= exp(X);
Sinh:= 0.5*(temp - 1/temp );
end;
{ ////////////////////////////////////////////// }
Function Tanh( X: real): real;
begin
Tanh:= Sinh(X)/Cosh(X);
end;
{ ////////////////////////////////////////////// }
Function XtoY( X,Y:Real ):Real;
begin
XtoY:= exp( Y * Ln( X ) );
end;
{///////////////////////////////////////////////}
Function ArcCosh( X:Real ):Real;
begin
ArcCosh:= Ln( X + sqrt( sqr(X) - 1 ) );
end;
{////////////////////////////////////////////////}
Procedure Iterate_Freq_1( wp:real; No: integer); { Calculation of Iterated }
{ wp_lo for the Lower StopBand; Next Iterate High StopBand with Next R }
var wp_1,wp_2,wp_3 : real; { Frequency Variables in Linear Interpol }
L1,L2,L3 : real; { Losses at Frequency Variables Above }
error : real; { Differences in Frequencies }
del : real; { Attenuation in Loss Function }
Timer : integer; { Aborts if No Convergence }
Label 10;
Function Loss( wp: real; No: integer ): real;
{ wp is Ripple Freq in Use }
var temp: real;
begin
temp:= abs(wo_geom/(wp_hi-wp)*(wo_geom/Freq[No] - Freq[No]/wo_geom));
del:= 10.0*Log10(1+sqr(eta*Cosh(order*ArcCosh(temp)))) - Att[No];
Loss:= del;
end;
begin
del:= 1;
wo_geom:= sqrt(wp*wp_hi); { Calculate Geometric Center Frequency }
L1:= Loss(wp,No); { Loss at wp_lo = dB Ripple }
wp_1:= wp;
wp_2:= 0.5*(wp + Freq[No]);{ Select Another Frequency Which Contains Zero }
wo_geom:= sqrt(wp_2*wp_hi); { Recalculate Geometric Center }
L2:= Loss(wp_2,No);
Timer:= 1;
while abs(del) > 0.01 do
begin
if Timer >= 10 then goto 10;
wp_3:= (L1*wp_2 - L2*wp_1)/(L1-L2);
wo_geom:= sqrt(wp_3*wp_hi); { Must Recalculate Geometric Center }
L3:= Loss(wp_3,No);
if L1*L3 > 0.0 then
begin
L1:= L3;
wp_1:= wp_3;
if wp_1 > wp_lo_max then wp_1:= wp_lo_max;
end;
if L1*L3 <= 0.0 then
begin
L2:= L3;
wp_2:= wp_3;
if wp_2 > wp_lo_max then wp_2:= wp_lo_max;
end;
Timer:= Timer + 1;
end;
10: wp_new:= wp_3; { New Lower Ripple Frequency }
if (del < 0.01) and ( Timer = 1 ) then wp_new:= wp_2; { In Case wp_2 is }
end; { Right On }
{ ================================================================== }
Procedure Iterate_Freq_2( wp: real; No: integer); { For Upper StopBand }
var wp_1,wp_2,wp_3 : real; { Frequency Variables in Linear Interpol }
L1,L2,L3 : real; { Losses at Frequency Variables Above }
error : real; { Differences in Frequencies }
del : real; { Attenuation in Loss Function }
Timer : integer; { Aborts if No Convergence }
label 10;
Function Loss( wp: real; No: integer ): real;
var temp: real;
begin
temp:= abs(wo_geom/(wp-wp_lo)*(wo_geom/Freq[No]-Freq[No]/wo_geom));
del:= 10.0*Log10(1+sqr(eta*Cosh(order*ArcCosh(temp)))) - Att[No];
Loss:= del;
end;
begin
del:= 1;
wo_geom:= sqrt(wp_lo*wp);
L1:= Loss(wp,No); { Loss at wp_hi = dB Ripple }
wp_1:= wp;
wp_2:= 0.5*(wp + Freq[No]);
wo_geom:= sqrt(wp_2*wp_lo);
L2:= Loss(wp_2,No);
Timer:= 1;
while abs(del) > 0.01 do
begin
if Timer >= 10 then goto 10;
wp_3:= (L1*wp_2 - L2*wp_1)/(L1-L2);
wo_geom:= sqrt(wp_3*wp_lo);
L3:= Loss(wp_3,No);
if L1*L3 > 0.0 then
begin
L1:= L3;
wp_1:= wp_3;
if wp_1 < wp_hi_min then wp_1:= wp_hi_min;
end;
if L1*L3 <= 0.0 then
begin
L2:= L3;
wp_2:= wp_3;
if wp_2 < wp_hi_min then wp_2:= wp_hi_min;
end;
Timer:= Timer + 1;
end;
10: wp_new:= wp_3;
if ( del < 0.01) and ( Timer = 1 ) then wp_new:= wp_2;
end;
{ ================================================================== }
procedure Inser_Loss( var order:integer; Am_dB:real);
type matrix = array[0..20] of real;
var W : real; { Fractional Bandwidth }
wo : real; { Geometric Center Frequency }
a,b : matrix; { Array Holding Values - Matthaei 4.05-02 }
g : matrix; { Elemental Values }
Beta : real;
gamma : real;
gamma2 : real;
k : integer; { Loop Counter }
Sum : real;
begin
W:= (wp_hi-wp_lo)/wo_geom;
Beta:= Ln(1/Tanh( Am_dB/17.37));
gamma:= sinh(beta/(2*order)); { Eq 4.05-02 Matthaei }
gamma2:= sqr(gamma);
for k:= 1 to order do
begin
a[k]:= sin((2*k-1)*Pi/(2*order));
b[k]:= gamma2 + sqr(sin(k*Pi/order));
end;
g[0]:= 1.0;
g[1]:= 2*a[1]/gamma;
for k:= 2 to order do
begin
g[k]:= 4*a[k-1]*a[k]/(b[k-1]*g[k-1]);
end;
if ( order mod 2 = 1 ) then
g[order + 1]:= 1.0
else
g[order + 1]:= sqr(1.0/tanh(0.25*Beta));
sum:= 0.0;
for k:= 1 to order + 1 do
begin
sum:= sum + g[k];
end;
IL:= 4.343*sum*4*g[0]*g[order+1]/(W*Qu*sqr(g[0]+g[order+1]));
end;
{ ================================================================== }
procedure maxi;
var IO_Error : integer;
begin
clrscr;
gotoXY(1,8);
writeln;
writeln(' P A S S B A N D M A X I M I Z E R');
writeln(' Version 2.0.2 ');
writeln(' Jeff Crawford TRW ');
delay(1000);
clrscr;
gotoXY(10,10);
write('Enter Minimum f-low and Maximum f-high in MHz ');
{$I-}
repeat
IO_Error:=0;
readln(wp_lo_max,wp_hi_min);
IO_Error:=IOResult;
if IO_Error <>0 then writeln ('Error; please re-enter data correctly.');
until IO_Error=0;
{$I+}
wp_lo:= wp_lo_max;
wp_hi:= wp_hi_min;
write(' ');
write('Enter dB Ripple in Passband & % Freq Error ');
{$I-}
repeat
IO_Error:=0;
readln(L_db,Freq_margin);
IO_Error:=IOResult;
if IO_Error <>0 then writeln ('Error; please re-enter data correctly.');
until IO_Error=0;
{$I+}
write(' ');
write('Enter Approx Resonator Unloaded Q ');
{$I-}
repeat
IO_Error:=0;
readln(Qu);
IO_Error:=IOResult;
if IO_Error <>0 then writeln ('Error; please re-enter data correctly.');
until IO_Error=0;
{$I+}
freq_margin:= freq_margin*0.01;
eta:= sqrt(XtoY(10.0,0.1*L_db)-1.0);
write(' ');
write('Enter Number of Lower Stop-Band Freq Requirements ');
{$I-}
repeat
IO_Error:=0;
readln(N_lo);
IO_Error:=IOResult;
if IO_Error <>0 then writeln ('Error; please re-enter data correctly.');
until IO_Error=0;
{$I+}
write(' ');
write('Enter Number of Upper Stop-Band Freq Requirements ');
{$I-}
repeat
IO_Error:=0;
readln(N_hi);
IO_Error:=IOResult;
if IO_Error <>0 then writeln ('Error; please re-enter data correctly.');
until IO_Error=0;
{$I+}
write(' ');
write('Enter Lower, Upper Bounds on Filter Order ');
{$I-}
repeat
IO_Error:=0;
readln(ord_lo,ord_hi);
IO_Error:=IOResult;
if IO_Error <>0 then writeln ('Error; please re-enter data correctly.');
until IO_Error=0;
{$I+}
order:= ord_lo;
writeln;
write(' ');
write('Is a Hard Copy of Results Desired Y/N ? ');
readln(stat_ptr);
stat_ptr:= upcase(stat_ptr);
clrscr;
writeln;
writeln(' Enter Lower Stop-Band Freqs & Respective Attenuations ');
writeln;
for i:= 1 to N_lo do { Input Stop-Band Attenuation Requirements }
begin
gotoXY(25,i+5);
write('[',i,'] = ');
{$I-}
repeat
IO_Error:=0;
readln(Freq[i],Att[i]);
IO_Error:=IOResult;
if IO_Error <>0 then writeln ('Error; please re-enter data correctly.');
until IO_Error=0;
{$I+}
end;
clrscr;
writeln;
writeln(' Enter Upper Stop-Band Freqs & Respective Attenuations ');
writeln;
for i:= 1 to N_hi do
begin
gotoXY(25,i+5);
write('[',i,'] = ');
{$I-}
repeat
IO_Error:=0;
readln(Freq[i+N_lo],Att[i+N_lo]);
IO_Error:=IOResult;
if IO_Error <>0 then writeln ('Error; please re-enter data correctly.');
until IO_Error=0;
{$I+}
end;
clrscr;
writeln;
write(' Min wp = ',wp_lo_max:8:3,' Max wp = ',wp_hi_min:8:3);
writeln(' dB Ripple = ',L_db:5:2);
writeln(' Resonator Qu = ',Qu:6:2);
writeln;
writeln(' Stop-Band Attenuation Requirements ');
writeln;
write(' Frequency Attenuation ');
writeln;
for i:= 1 to N_lo + N_hi do
begin
write(' F',i,' ');
writeln(Freq[i]:10:3,' MHz . . . . . . . .. . . . ',Att[i]:5:2,' dB');
end;
for i:= 1 to 2 do
begin
write('=============================================================');
writeln('=================');
end;
writeln;
write('Order Low Fp Up Fp Loss dB ');
for i:= 1 to N_lo+N_hi do
begin
write(' F',i,' ');
end;
writeln;
writeln;
if stat_ptr = 'Y' then
begin
writeln(LST);
write(LST,' Min wp = ',wp_lo_max:8:3,' Max wp = ',wp_hi_min:8:3);
writeln(LST,' dB Ripple = ',L_db:5:2);
writeln(LST,' Resonator Qu = ',Qu:6:2);
writeln(LST);
writeln(LST,' Stop-Band Attenuation Requirements ');
writeln(LST);
write(LST,' Frequency Attenuation ');
writeln(LST);
for i:= 1 to N_lo + N_hi do
begin
write(LST,' F',i,' ');
writeln(LST,Freq[i]:10:3,' MHz . . . . . . . .. . . . ',Att[i]:5:2,' dB');
end;
for i:= 1 to 2 do
begin
write(LST,'=============================================================');
writeln(LST,'=================');
end;
writeln(LST);
write(LST,'Order Low Fp Up Fp Loss dB ');
for i:= 1 to N_lo+N_hi do
begin
write(LST,' F',i,' ');
end;
writeln(LST);
writeln(LST);
end;
order:= ord_lo;
while order <= ord_hi do { For Order Selected }
begin
Flag1:= False;
del:= 1.0;
min:= 1.0E10;
wo_geom:= sqrt(wp_lo_max*wp_hi_min);
for i:= 1 to N_lo do { If Margins First Time Through Are Negative }
begin { Need A Higher Order Filter }
wp:= wo_geom/(wp_hi_min-wp_lo_max);
wp:= abs(wp*(wo_geom/Freq[i] - Freq[i]/wo_geom));
del:= 10.0*Log10( 1 + sqr(eta*Cosh(Order*Arccosh(wp))));
delta_dB[i]:= del - Att[i];
if delta_dB[i] < 0.0 then Flag1:= True;
if delta_dB[i] < min then
begin
min:= delta_dB[i];
Num_lo:= i;
end;
end; { Flag1 Is Set if Any Negative Margins Appear }
del:= 1.0;
min:= 1.0E10;
for i:= 1 to N_hi do
begin
wp:= wo_geom/(wp_hi_min-wp_lo_max);
wp:= abs(wp*(wo_geom/Freq[i+N_lo]-Freq[i+N_lo]/wo_geom));
del:= 10.0*Log10( 1 + sqr(eta*Cosh(Order*Arccosh(wp))));
delta_dB[i+N_lo]:= del - Att[i+N_lo];
if delta_dB[i+N_lo] < 0.0 then Flag1:= True;
if delta_db[i+N_lo] < min then
begin
min:= delta_dB[i+N_lo];
Num_hi:= i+N_lo;
end;
end;
if Flag1 = True then { Output Best Possible Performance For Neg Margin }
begin
write('',order:2,' ');
for i:= 1 to N_lo+N_hi do
begin
write(Delta_dB[i]+Att[i]:8:3,' ');
end;
writeln;
if stat_ptr = 'Y' then
begin
write(LST,'',order:2,' ');
for i:= 1 to N_lo+N_hi do
begin
write(LST,Delta_dB[i]+Att[i]:8:3,' ');
end;
writeln(LST);
end;
end;
if (Flag1 = False) then { When Filter Order is High Enough, Optimize }
begin { Ripple BandWidths for Best Passband Width }
wo_geom:= sqrt(wp_lo*wp_hi);
stat:= 1.0E10;
while stat > freq_margin do
begin
wp_lo_save:= wp_lo;
wp_hi_save:= wp_hi;
Iterate_Freq_1(wp_lo,Num_lo); { Find New Lower wp }
wp_lo:= wp_new;
del:= 1.0;
min:= 1.0E10;
wo_geom:= sqrt(wp_lo*wp_hi);
for i:= 1 to N_hi do { Find Upper StopBand Freq With Least Margin}
begin
wp:= wo_geom/(wp_hi-wp_lo);
wp:= abs(wp*(wo_geom/Freq[i+N_lo] - Freq[i+N_lo]/wo_geom));
del:= 10.0*Log10( 1 + sqr(eta*Cosh(Order*Arccosh(wp))));
delta_dB[i+N_lo]:= del - Att[i+N_lo];
if delta_dB[i+N_lo] < min then
begin
min:= delta_dB[i+N_lo];
Num_hi:= i+N_lo;
end;
end;
Iterate_Freq_2(wp_hi,Num_hi); { Calculate New Upper wp }
wp_hi:= wp_new;
del:= 1.0;
min:= 1.0E10;
wo_geom:= sqrt(wp_lo*wp_hi);
for i:= 1 to N_lo do { Evaluate Which Lower Freq Has Min Margin }
begin
wp:= wo_geom/(wp_hi-wp_lo);
wp:= abs(wp*(wo_geom/Freq[i]-Freq[i]/wo_geom));
del:= 10.0*Log10( 1 + sqr(eta*Cosh(Order*Arccosh(wp))));
delta_dB[i]:= del - Att[i];
if delta_db[i] < min then
begin
min:= delta_dB[i];
Num_lo:= i;
end;
end;
stat:=(abs(wp_lo-wp_lo_save)+abs(wp_hi-wp_hi_save))/wo_geom;
wp_new_1:= wp_lo;
wp_new_2:= wp_hi;
end;
Inser_Loss(order,L_dB);
for i:= 1 to N_lo+N_hi do
begin
temp:= wo_geom/(wp_hi-wp_lo);
temp:= abs(temp*(wo_geom/Freq[i]-Freq[i]/wo_geom));
del:= 10.0*Log10( 1 + sqr(eta*Cosh(Order*Arccosh(temp))));
delta_dB[i]:= del - Att[i];
end;
write('',order:2,' ',wp_new_1:8:3,' ',wp_new_2:8:3,'');
write(IL:8:3,' ');
for i:= 1 to N_lo+N_hi do
begin
write(Delta_dB[i]+Att[i]:8:3,' ');
end;
writeln;
if stat_ptr = 'Y' then
begin
write(LST,'',order:2,' ',wp_new_1:8:3,' ',wp_new_2:8:3,'');
write(LST,IL:8:3,' ');
for i:= 1 to N_lo+N_hi do
begin
write(LST,Delta_dB[i]+Att[i]:8:3,' ');
end;
writeln(LST);
end;
end;
wp_lo:= wp_lo_max;
wp_hi:= wp_hi_min;
Flag1:= False;
order:= order + 1;
end;
write(' ');
writeln(' CR to Continue');
readln(wp_lo);
end;{end maxi}
var ink : boolean;
begin {main}
repeat
ink:=false;
maxi;
writeln(' To rerun the program, type R ');
read (inkey);
if inkey='r' then ink:=true;
if inkey='R' then ink:=true;
until not ink;
end.