  /************************************************
  
    COPYRIGHT 1987  Steven D. Swift
    Rights to copy are granted provided that the
    program is neither sold nor used for commercial
    purposes and that this notice stay with all
    copies.
    
history:

    rev 0:    november 02, 1987    Steven D. Swift, P.E.
                                   Seattle, Washington
    rev 1:    august 31, 1990   updated array initialization
                                modified number of digits in out
    

****************************************************
        Butterworth.c
        
this program calculates the component values for
nth order butterworth filters.  Either low pass
or high pass, with either capacitive or inductive
inputs.  The input and output load are restricted
to being the same value and resistive, e.g; 50 ohms.
No other restrictions are placed on the values and
the program does not check for standard values.
Although the output is in a form most appropriate for
filters that end up with L's in uH and C's in pF.

The formulas used in this program and the examples
used to test it came from:

    Introduction to Radio Frequency Design,
    W.H. Hayward, Prentice-Hall 1982.

Required inputs are:

        Fc:            3db frequency, in MHz
        Ro:            source and load impedance, in ohms
        n:            order of desired filter
        hp or lp:    type of filter
        cap or ind:    input stage, capacitive or inductive

The outputs are:

        component value, inductor or capacitor indicated by
        units printed.

--------------------------------------------------------------


***********************************************************/

#include <stdio.h>
#include <math.h>

    
    float L[25] ;                /* inductors    */
    float C[25] ;                /* capacitors    */
    float g[25];                /* coeficient register            */
    
main() 
{

    float pi = 3.141592654; 
    double sin();                /* need sine to calculate coef     */
    int k = 0;                    /* counter for coeficients        */
    float Fc ;            /* 3dB cutoff frequency    hertz        */
    float Wc ;            /* 3dB cutoff frequency    radians        */
    float Ro = 50.0;            /* source and load impedance    */
    int input;                    /* alpha for inductive input    */
                                /* alpha for capacitive input    */
    int n = 3;                    /* order of filter                */
    int i = 0;                    /* dummy counter                */
    int type;                    /* type of filter: lp or hp        */
    float meg = 1000000.0;



/* input user chosen variables first */

    printf("\n\nBUTTERWORTH FILTER PROGRAM\n\n");

    printf("Input the order of the filter (25 max):  ");
    scanf("%d", &n);
    printf("\n");

    if(n>25){
	printf("\nOrder too large!\n");
	exit();
	}

    init(n);                /* initialize arrays to all zeroes */

    printf("Input the type of filter (1=hp or 2=lp):  ");
    scanf("%d", &type);
    printf("\n");

    printf("Type of input stage (1=ind or 2=cap):  ");
    scanf("%d", &input);
    printf("\n");

    printf("Input cutoff frequency (MHz):  ");
    scanf("%f",&Fc);
    Wc = 2*pi*Fc*meg;
    printf("\n");

    printf("Input source and load resistance (ohms):  ");
    scanf("%f",&Ro);
    printf("\n");

/*
   calculate normalized filter coeficients and store them in
   the array g[]
*/

    for(i = 1; i <= n; i++)
        g[i] = 2*sin( (2*i-1)*pi/(2*n) );


/*
    test for types of filters and input stage, then perform
    the appropriate calculations by calling the appropriate
    function.  these functions do not return values, but
    modify the arrays L[] and C[] directly, getting inputs
    from the variables typed in by the user and from g[].
*/


    if ( (type==1) && (input==1) )
        for( i = 1; i <= n ; i++)
            hpind(Wc,g[i],Ro,i);

    else if ( (type==2) && (input==2) )
        for( i = 1; i <= n ; i++)
            lpcap(Wc,g[i],Ro,i);

    else if ( (type==1) && (input==2) )
        for( i = 1; i <= n ; i++)
            hpcap(Wc,g[i],Ro,i);
        
    else if ( (type==2) && (input==1) )
        for( i = 1; i <= n ; i++)
            lpind(Wc,g[i],Ro,i);

    else printf("Type of filter incorrect. Please try again.\n\n");

    output(n,Fc);    /* output results */
}


/*  all the functions used by main are located starting here */

hpcap(x,y,z,k)    /* x is radian freq, y is gk, z is Ro and k is count */

    float x,y,z;
    int k;
    {
    if(isodd(k)==1)
        C[k] = 1.0/(x*y*z);
    else
        L[k] = z/(x*y);
    }

hpind(x,y,z,k)        /* x is radian freq, y is gk, z is Ro and k is count */

    float x,y,z;
    int k;
    {
    if(isodd(k)==0)
        C[k] = 1.0/(x*y*z);
    else
        L[k] = z/(x*y);

    }

lpcap(x,y,z,k)        /* x is radian freq, y is gk, z is Ro and k is count */

    float x,y,z;
    int k;
    {
    if(isodd(k)==1)
        C[k] = y/(z*x);
    else
        L[k] = (y*z)/x;
    }

lpind(x,y,z,k)        /* x is radian freq, y is gk, z is Ro and k is count */

    float x,y,z;
    int k;
    {
    if(isodd(k)==0)
        C[k] = y/(z*x);
    else
        L[k] = (z*y)/x;
    }


/*  isodd tests if an integer is odd or not, for use in finding
    whether or not to calculate an L or a C element  */
    
isodd(x)

int x;
{
    int i=1;
    if ( (x % 2) == 0)
        i=0;        /* returns 0 if even, 1 if odd */
    return(i);
}


/* output():  prints out the results of the program */

output(n,f)

float f;
int n;
{
    int i;
    printf("\nValues for %d order Butterworth filter @ %.4e MHz",n,f);
    printf("\n Element    Inductors    Capacitors\n\n");
    
    for (i=1; i<=n; i++)
        {
        if (L[i]>0)
            printf("  #: %d        %.3fuH\n",i,L[i]*1.0e6);
        if (C[i]>0)
            printf("  #: %d                     %.2fpF\n",i,C[i]*1.0e12);
        }
}    

/*  initialize array variables  */

init(n)
int n;
{
    int i;
    for (i=0; i<=n; i++)
        {
        g[i] = 0.0;
        L[i] = 0.0;
        C[i] = 0.0;
        }
}
/* that's the end */
