+++ /dev/null
-/* atlc - arbitrary transmission line calculator, for the analysis of
-transmission lines are directional couplers.
-
-Copyright (C) 2002. Dr. David Kirkby, PhD (G8WRB).
-
-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 package_version 2
-of the License, or (at your option) any later package_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 program; if not, write to the Free Software
-Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
-USA.
-
-Dr. David Kirkby, e-mail drkirkby at ntlworld.com
-
-*/
-
-#include "config.h"
-
-#include "definitions.h"
-#include "exit_codes.h"
-
-#ifdef HAVE_STDLIB_H
-#include <stdlib.h>
-#endif
-
-#ifdef SYS_TYPES_H
-#include <sys/types.h>
-#endif
-
-#ifdef HAVE_STRINGS_H
-#include <strings.h>
-#endif
-
-#ifdef HAVE_STRING_H
-#include <string.h>
-#endif
-
-#ifdef HAVE_TIME_H
-#include <time.h>
-#endif
-
-#ifdef HAVE_MATH_H
-#include <math.h>
-#endif
-
-
-extern int errno;
-int verbose=2;
-
-/* desgin_coupler does two very different things in the one program
-1) Given a frequency range, the required coupling factor, it calcuates
-the odd and even mode impedances needed for a coupler. It does this
-assuming the length of the coupler is lambda/4, although you can vary
-that on the command line with the -l option.
-
-2) Once the optimal values for the even and odd mode impedances are
-found, it itteratively looks up the odd and even mode impedances for two
-think lines of various widths (w) and spacings (s), looking for the
-combination that gives the best rms error between the required
-impedances and those that will result with the coupler design as
-presented.
-
-It is assumed by default that the height of the box is of one unit (1
-mm, 1" etc, but this may be changed on the command line. This will scale
-the parameters w and s by the same multiple.
-
-*/
-
-int main(int argc, char **argv) /* Read parameters from command line */
-{
- int q, Hflag=FALSE;
- int calculate_physical_dimensions=FALSE;
- int calculate_physical_dimensions_to_high_accuracy=FALSE;
- double er;
- double Zo=-1, length=-1, fmin, fmax, fmean, fstep=-1, cf, Zodd, Zeven;
- double f, vcf, vcf_for_quarter_wave_line, w, s, error, error_max=1e30;
- double wanted_coupling_factor_in_dB, step=0.02, fq;
- double Zeven_x=-1, Zodd_x=-1, best_s=-1, best_w=-1;
- double height_of_box=1.0;
- double best_Zodd=-1, best_Zeven=-1, best_Zo=-1;
-
- /* SGI's MipsPro compiler is very fussy. The following line, along
- with one right at the end, forces Zo_x to be set and used,
- alhtough it serves no other userful purpose but to keep the
- compiler happy */
- double Zo_x=1;
- while((q=get_options(argc,argv,"DeQqdCL:s:Z:H:")) != -1)
- switch (q)
- {
- case 'd':
- calculate_physical_dimensions=TRUE;
- break;
- case 'D':
- calculate_physical_dimensions=TRUE;
- calculate_physical_dimensions_to_high_accuracy=TRUE;
- break;
- case 'e':
- give_examples_of_using_design_coupler();
- break;
- case 'C':
- print_copyright((char *) "2002");
- Hflag=TRUE;
- exit_with_msg_and_exit_code("",OKAY);
- break;
- case 'L':
- length=atof(my_optarg); /* Sets the length of coupler */
- break;
- case 'H':
- height_of_box=atof(my_optarg); /* Set height of coupler's enclosure */
- Hflag=TRUE;
- break;
- case 's': /* Set frequncy steps in which coupling is computed */
- fstep=atof(my_optarg);
- break;
- case 'Z': /* Set the characteristic impedance - default is 50 Ohms */
- Zo=atof(my_optarg);
- break;
- case 'q': /* Run in quite mode, giving less output */
- verbose--;
- break;
- case '?':
- usage_design_coupler();
- break;
- } /* End of the switch statement */
-
- if(argc-my_optind != 3) /* This should be so hopefully !! */
- {
- usage_design_coupler();
- exit_with_msg_and_exit_code("",PROGRAM_CALLED_WITH_WRONG_NUMBER_OF_ARGUMENTS);
- }
- wanted_coupling_factor_in_dB=atof(argv[my_optind]);
- fmin=atof(argv[my_optind+1]);
- fmax=atof(argv[my_optind+2]);
- fmean=(fmin+fmax)/2.0;
- if(fstep <0 )
- fstep=(fmax-fmin)/4.0;
-
- if (wanted_coupling_factor_in_dB <= 0.0 ) /* Only 0 can happen */
- {
- /* I don't think this can happen unless the user enter 0 as the
- first parameter, as a negative number entered will be taken as a
- command line option */
- fprintf(stderr,"\nThe coupled power must be less than the input power.");
- fprintf(stderr," But please enter a\n*positive* number in dB for the");
- fprintf(stderr," first command line parameter. If you want a \ncoupler");
- fprintf(stderr," with a coupled port that is 12 dB down on the input");
- fprintf(stderr," power, covering\n144-146 MHz, enter this as:\n\n");
- fprintf(stderr,"design_coupler 12 144 146\n\n");
- fprintf(stderr,"If you want the physical dimensions of the coupler");
- fprintf(stderr," designed for you, add the\n-d option on the command");
- fprintf(stderr," line, like this:\n\ndesign_coupler -q -12 144 146\n\n");
- fprintf(stderr,"If you run design_coupler with no command line");
- fprintf(stderr," arguments, like this:\n\ndesign_coupler\n\n");
- fprintf(stderr,"then design_coupler will print some information,");
- fprintf(stderr," showing *all* the options. \nIf you run design_coupler");
- fprintf(stderr," with the -e option like this:\n\n");
- fprintf(stderr,"design_coupler -e\n\n");
- fprintf(stderr,"lots of examples will be shown of the correct usage.\n");
- exit_with_msg_and_exit_code("",IMPOSSIBLE_COUPLING_COEFFICIENT);
- }
- if (fmax <= fmin)
- {
- fprintf(stderr,"The second command line argumentent you gave, which");
- fprintf(stderr," is for the *minimum*\noperating frequenncy in MHz,");
- fprintf(stderr," is less than the third argument, which is the\n");
- fprintf(stderr,"*maximum* operating frequency in MHz.\n\n");
- fprintf(stderr,"If you want a coupler");
- fprintf(stderr," with a coupled port that is 12 dB down on the input\n");
- fprintf(stderr,"power, covering 144-146 MHz, enter this as:\n\n");
- fprintf(stderr,"design_coupler 12 144 146\n\n");
- fprintf(stderr,"If you want the physical dimensions of the coupler");
- fprintf(stderr," designed for you, add the\n-d option on the command");
- fprintf(stderr," line, like this:\n\ndesign_coupler -d 12 144 146\n\n");
- fprintf(stderr,"If you run design_coupler with no command line arguments,");
- fprintf(stderr," then design_coupler\nwill print some information,");
- fprintf(stderr," showing *all* the options. If you run\ndesign_coupler");
- fprintf(stderr," with the -e option like this:\n\n");
- fprintf(stderr,"design_coupler -e\n\n");
- fprintf(stderr,"lots of examples will be shown of the correct usage.\n");
- fprintf(stderr,"Exiting ...\n");
- exit_with_msg_and_exit_code("",FMAX_NOT_ABOVE_FMIN);
- }
- if (Zo < 0.0)
- Zo=50.0;
- if(length<0.0)
- length=75.0/fmean; /* By default, make it a quarter wave long */
- /* The following sent in an email by Paul AA1L, sums the theory up
- You make Zo=50=sqrt(Zoo*Zoe) and
- c=(Zoe-Zoo)/(Zoe+Zoo), c being the voltage coupling coefficient.
- I.e., for a 20dB coupler c=0.1 is the midband
- coupling.
- Coupling varies as sin^2(f/fq), fq being frequency where the coupled
- length is a quarter wave.
-
- HOWEVER, the above is not quite the full story, as that says coupling
- peaks at sin(1), when in fact its sin(Pi/2)
- */
-
- /* vfc stands for 'voltage coupling factor' */
-
- /* I need to find values for Zodd and Zeven to use, but first convert
- the coupling factor on the command line into the voltage coupling
- factor c */
-
- /* vfc stands for 'voltage coupling factor' */
-
- /* When the line is a quarter wave, one can get any amount of coupling
- you want, including a vfc of 1, in which case all the power transfers
- to the coupled port. Normally, the vcf will be less than 1.0. for a 20
- dB couplier is it 0.1 */
-
- vcf_for_quarter_wave_line=1.0/pow(10.0,wanted_coupling_factor_in_dB/20.0);
-
- fq=75/length; /* frequency at which line is a quarter wave long */
-
- /* If the line is less than a quarter wave long, then less power is
- coupled, so to compensate we need to increase the voltage coupling
- factor 'vcf above that of the value for a quarter wave line.
- Since the 'vcf' varies as sin(0.5 *PI * f/fq)^2, where
- fq is the frequency at which the line is a quarter-wave long, we must
- divide the vcf_for_quarter_wave_line by sin(0.5 *PI*f/fq)^2 to get
- the required vcf. */
- vcf=vcf_for_quarter_wave_line*(1.0/sin(0.5*M_PI*fmean/fq));
- /* Check that the voltage coupling factor does not exceed one */
- if ( vcf > 1.0 )
- {
- fprintf(stderr,"\n*****ERROR****\n");
- fprintf(stderr,"Sorry, you can't make a %6.3f dB coupler with a coupled line of %7.4f m long.\n",wanted_coupling_factor_in_dB, length);
- fprintf(stderr,"Either couple off a smaller fraction of the main power to the coupled port,\n");
- fprintf(stderr,"or make the line closer to an odd multiple of a quarter wave.\n");
- fprintf(stderr,"Odd mulitples of a quarter wave are: %.4f, %.4f, %.4f, %.4f .. m\n", 75/fmean, 3*75/fmean, 5*75/fmean, 7*75/fmean);
- exit_with_msg_and_exit_code("",IMPOSSIBLE_TO_MAKE_COUPLER_THAT_LENGTH);
- }
-
- /* After mucking around with Mathematica a bit, I found it was
- possible to invert the equations */
-
- Zodd = sqrt(1-vcf)*Zo/sqrt(1+vcf);
- Zeven=Zo*Zo/Zodd;
-
- printf("\nFor a %.3f dB %.3f Ohm coupler with a length of %.4f m,\n",wanted_coupling_factor_in_dB, Zo, length);
- printf("you need to have an odd-mode impedance Zodd of %.3f Ohms and\n",Zodd);
- printf("an even mode impedance Zeven of %.3f Ohms\n\n",Zeven);
- if(verbose >=1) /* Only print if user does not specifiy and -qq options */
- {
- printf("%.3f dB down <-- ************************** ---> %3.3f Ohm termination\n\n",wanted_coupling_factor_in_dB,Zo);
- printf("Drive this port --> ************************** ---> %3.3f Ohm termination\n",Zo);
- printf(" <------- %8.4f m ----->\n",length);
- printf("\nDrive Port 1, coupler out of port 2 and terminate the other ports in Zo\n");
- printf("Such a coupler will have the response indicated below.\n\n");
- /*printf("length =%.4f mean=%.3f vcf=%.3f vcf_for_quarter_wave_line=%.3f \n",length, fmean, vcf, vcf_for_quarter_wave_line);*/
- }
- for(f=fmin; f<=fmax; f+=fstep)
- {
- cf=20*log10(vcf*sin(0.5*M_PI*f/fq)); /* This is what is now needed for some given length (and so fq) */
- if(verbose == 2)
- printf("f = %7.3f MHz coupling is %.3f dB down on the main arm\n",f,cf);
- }
- printf("\nYou may force the length to be any value you want using the -L option - it does\nnot have to be %.4f metres long\n",length);
- if(calculate_physical_dimensions==FALSE)
- {
- printf("You may try to find a coupler with these dimensions using the -d option\n\n");
- printf("Currently the -d option is not that fast, as it uses a brain-dead algorithm\n");
- printf("Hopefully one day the algorithm will be speeded up.\n");
- }
- if(calculate_physical_dimensions==TRUE)
- {
- er=1.0;
- printf("Please be patient - this will take a few minutes or so\n");
- for(s = 0.02; s<=100; s+=step)
- {
- for(w = 0.02; w<= 11.0; w += step)
- {
- /* Results are calculated assuming the box is one unit (mm, inch
- etc) high and later scaled */
-
- calculate_Zodd_and_Zeven(&Zodd_x, &Zeven_x, &Zo_x, w, 1.0, s, er);
- error=pow(Zodd-Zodd_x,2.0) + pow(Zeven-Zeven_x,2.0);
- if( error < error_max )
- {
- best_s=s;
- best_w=w;
- best_Zo=sqrt(best_Zo * best_Zeven);
- best_Zodd=Zodd;
- best_Zeven=Zeven;
- error_max=error;
- }
- }
- }
- printf("w = %.4f s = %.4f which gives Zo = %.4f Zodd = %.4f Zeven = %.4f\n",best_w, best_s, best_Zo, best_Zodd, best_Zeven);
- /* Now try to get closer, if -D option given */
- if (calculate_physical_dimensions_to_high_accuracy == TRUE)
- {
- for(s = best_s-step; s<=best_s+step; s+=step/1000)
- {
- for(w = best_w-step; w<= best_w+step; w += step/1000)
- {
- calculate_Zodd_and_Zeven(&Zodd_x, &Zeven_x, &Zo_x, w, 1.0, s, er);
- error=fabs(Zodd-Zodd_x) + fabs(Zeven-Zeven_x);
- if( error < error_max )
- {
- best_s=s;
- best_w=w;
- best_Zodd=Zodd;
- best_Zeven=Zeven;
- error_max=error;
- }
- }
- }
- }
- best_Zo=sqrt(best_Zodd * best_Zeven);
- if(verbose <= 0)
- {
- printf("|-----------^------------------------------------------------------------------|\n");
- printf("| | |\n");
- printf("| | <---w---><-----s----><---w--> |\n");
- printf("| H --------- -------- |\n");
- printf("| | |\n");
- printf("| | Er=1.0 (air) |\n");
- printf("------------v------------------------------------------------------------------\n");
- printf("<-----------------------------------------W----------------------------------->\n");
- }
- printf("H =%.4f w = %.4f s = %.4f\n",height_of_box, height_of_box*best_w, height_of_box*best_s);
- printf("W must be *at least* %.4f, but larger does not matter.\n",5*height_of_box+ 2*best_w*height_of_box + height_of_box*best_s);
- printf("These dimensions give Zo = %.4f Zodd = %.4f Zeven = %.4f Ohms\n", best_Zo, best_Zodd, best_Zeven);
- if(Hflag==FALSE)
- {
- printf("****NOTE ****\n");
- printf("Although H is shown as 1.0, it can be 1 mm, 1 cm or even 1 m. It is important\n");
- printf("that w is %.4f times whatever H is, and that s is %.4f times whatever H is, but the absolute numbers are irrelavant.\n",best_w, best_s);
- printf("If you know the height H of your enclosure, use the -H option to indicate\n");
- printf("its value. This will ensure all the dimensions are scaled automatically for you.\n");
- }
- printf("****NOTE 2****\n");
- printf("The length *must* be %.4f m if you use these dimensions for W, H, w and s.\n",length);
- printf("If %.4f m is inconvenient, change it with the -L option and recalculate\n to get new values of W, H, w and s\n",length);
- printf("See: http://atlc.sourceforge.net\n");
- printf("See: http://atlc.sourceforge.net/couplers.html\n");
- }
- return(OKAY);
-}