home *** CD-ROM | disk | FTP | other *** search
- /********************************************************************
- * ELLIPTICAL FILTER DESIGN
- * Given inputs of lamda (frequency transistion range), epsilon ( a measuer
- * of the pass band ripple, and the order of the sysetm, this program
- * will generate the necessary poles and zeros. It is based on a algorithmn
- * by Sindy Darlington.
- * steve punte 10-20-87
- */
- #include <stdio.h>
- #include <math.h>
- #define TRUE 1
- #define FALSE 0
- #define MX 50 /* Max number of poles or zeros */
- #define PIE 3.141592653
- #define scanf my_scanf
-
- struct cmplx_num{
- double real;
- double imag;
- };
-
- #define sqr(X) ( X )*( X )
- #define cset(X, Y, Z) X.real = Y; X.imag = Z
- #define cmpl(X) X.imag = - X.imag
- #define csub(X, Y, Z) Z.real = X.real - Y.real;\
- Z.imag = X.imag - Y.imag
- #define cmul(X, Y, Z) { \
- struct cmplx_num cmplx_tmp; \
- cmplx_tmp.real = X.real * Y.real - X.imag * Y.imag ; \
- cmplx_tmp.imag = X.real * Y.imag + X.imag * Y.real ; \
- Z.real = cmplx_tmp.real; \
- Z.imag = cmplx_tmp.imag; \
- }
- #define cdiv(X, Y, Z) { \
- struct cmplx_num cmplx_tmp; \
- double den; \
- den = sqr( Y.real ) + sqr( Y.imag ); \
- cmplx_tmp.real = X.real * Y.real + X.imag * Y.imag ; \
- cmplx_tmp.imag = X.imag * Y.real - X.real * Y.imag ; \
- Z.imag = cmplx_tmp.imag / den; \
- Z.real = cmplx_tmp.real / den; \
- }
-
- /* Common Recurrisions used in the algorithm */
- #define recurs10(A) A*A + sqrt( A*A*A*A - 1 )
- #define recurs12(Y, A) ( Y + 1/Y )/( 2.0 * A)
- #define recurs16(J) sqrt( 0.5 * ( J + 1/J ) )
- #define recurs18(JS) JS + sqrt( JS*JS + 1 )
- #define recurs20(P, A, PP) { \
- struct cmplx_num one, A_tmp, this_tmp; \
- cset( one, 1.0, 0.0); \
- cdiv( one, P, this_tmp); \
- csub( P, this_tmp, this_tmp); \
- cset( A_tmp, ( 1 / ( 2.0 * A ) ), 0.0); \
- cmul( this_tmp, A_tmp, PP ); \
- }
- main()
- {
- double lamda, epsilon;
- int M, i;
- double A0, A1, A2, A3, A4;
- double Y4[MX], Y3[MX], Y2[MX], Y1[MX], Y0[MX];
- double S0, S1, S2, S3, S4, S5;
- double J0, J1, J2, J3, J4, J5;
- double SJ0, SJ1, SJ2, SJ3, SJ4, SJ5;
- struct cmplx_num num;
- double den, K_coeff;
- struct cmplx_num P5[MX], P4[MX], P3[MX], P2[MX], P1[MX], P0[MX];
-
- /* Fetch necessary input data */
- fprintf( stderr, "Enter value of Lamda ->");
- scanf( "%f", &lamda );
- fprintf( stderr, "Enter value of Epsilon ->");
- scanf( "%f", &epsilon );
- do{
- fprintf( stderr, "Enter Order (odd) of system ->");
- scanf( "%d", &M );
- } while( M == 2 * (int)(M/2));
-
-
- /* Calcualtes the zeros */
- A0 = sqrt( lamda );
- A1 = recurs10( A0 );
- A2 = recurs10( A1 );
- A3 = recurs10( A2 );
- A4 = recurs10( A3 );
-
- for( i = 1; i <= M/2 ; i++ ) {
- Y4[i] = A4 / cos( (double)( 2.0 * i - 1.0 ) * PIE * 0.5 / (double)M );
- Y3[i] = recurs12( Y4[i], A3);
- Y2[i] = recurs12( Y3[i], A2);
- Y1[i] = recurs12( Y2[i], A1);
- Y0[i] = recurs12( Y1[i], A0);
-
- printf( "ZC 0.0 %f ; \n", Y0[i] );
- }
-
- /* Calculates the Poles */
- J4 = exp( (double)(M - 1) * log( 2.0 ) + (double)( M ) * log( A4 ) );
- J3 = recurs16( J4 );
- J2 = recurs16( J3 );
- J1 = recurs16( J2 );
- J0 = recurs16( J1 );
-
- fprintf( stderr, "Stop Band Atten = %f dB \n", 10 * log10( 1 + sqr( epsilon * sqr( J0 ))));
- SJ0 = 1 / epsilon ;
- SJ1 = J1 * (recurs18( SJ0 ));
- SJ2 = J2 * (recurs18( SJ1 ));
- SJ3 = J3 * (recurs18( SJ2 ));
- S4 = 2 * SJ3 ;
-
- S5 = exp( log( J4 / S4 + sqrt( ( J4 / S4 ) * ( J4 / S4 ) + 1 )) / (double)( M ) );
-
-
- for( i = 0; i <= M/2 ; i++ ) {
- double theta;
-
- theta = (double)i * PIE / (double)(M);
- cset( P5[i], (S5 * cos( theta) ), (S5 * sin( theta) ) );
-
- recurs20( P5[i], A4, P4[i]);
- recurs20( P4[i], A3, P3[i]);
- recurs20( P3[i], A2, P2[i]);
- recurs20( P2[i], A1, P1[i]);
- recurs20( P1[i], A0, P0[i]);
-
- if( fabs( P0[i].imag / P0[i].real ) < 0.0000001 ) {
- printf( "P %f ; \n", P0[i].real);
- }
- else printf( "PC %f %f ; \n", P0[i].real, P0[i].imag );
- }
-
-
- /* Calcualte the scaling constant */
- cset( num, 1.0, 0.0);
- for( i = 0; i <= M/2 ; i++ ) {
- if( fabs( P0[i].imag / P0[i].real ) < 0.0000001 ) { cmul( num, P0[i], num); }
- else {
- cmul( num, P0[i], num);
- cmpl( P0[i]);
- cmul( num, P0[i], num);
- }
- }
-
- den = 1.0 ;
- for( i = 1; i <= M/2 ; i++ ) {
- den *= sqr( Y0[i] );
- }
- K_coeff = fabs(num.real / den);
- printf( "K %f ; \n", K_coeff );
- }
-
-
-
- #undef scanf
- /* A lousy fucking patch for micro-soft C. It doesn't
- * seem to read floating point numbers properly.
- */
- my_scanf( str, reg)
- char *str;
- union {
- int x;
- double y;
- char t;
- } *reg;
-
- {
- double atof();
- if( !strcmp( str, "%f") ) {
- char temp[40];
- scanf( "%s", temp);
- reg->y = atof( temp);
- }
- else scanf( str, reg);
- }
-