/*************************************/

/**         Introduction            **/

/*************************************/

 

This explains how to use digital filters in FUNC_X codes.

Updated on January 10, 2006, e2e-3.1.1

 

/*************************************/

/**         HOW TO USE              **/

/*************************************/

 

/**

likes with >> is the code to be added in FUNC_X

(1) in MemberCecl

>> DF aFilter;

 

(2) in Constructor

>> aFilter.addKZPHz( xxx );

or using any other functions defining gain, zeros and ppoles

To set the initial condition or to force quad, use

>> aFilter.initCondition( x0, v0 ); aFilter.forcceQuad();

To printout various information, use

>> printAandB or printKZP

 

(3) in equation

to apply filter

>> aFilter.filterApply( input );

to reset the filter,

>> aFilter.filterReset();

**/

 

/*************************************/

/**        MAIN FUNCTIONS           **/

/*************************************/

 

/** returns the current output using cascaded direct form II second order sections **/

  adlib_real filterApply( const adlib_real inputNow );

 

/** force to reset the filter to the initial state **/

  void filterReset( void );

 

/* conditional reset */

  bool filterReset( const adlib_real resetSig_arg, adlib_real *outputVal = 0 );

 

/** set the initial condition and velocity.

      filterApply(0) = y0

      filterApply(1) = y0 + velocity * delT

**/

  void initCondition( adlib_real y0, adlib_real velocity );

 

/** force to use quad **/

  void forceQuad( void );

 

/** print A and B of SOS sections to output stream */

  void printAandB( ostream *strm, const string &msg = "" );

 

/** print s domain zeros and poles. If forMatlab is true, it generates an expression which can be pasted in matlab directly. */

  void printKZP( ostream *strm, const string &msg = "", const bool forMatlab = false );

 

/** calculate the complex transfer function */

  adlib_complex transferFunc( const adlib_real freq, const bool digital = true ) const;

 

/** set the name of the filter. Useful for debugging */

  void setName( const string name_arg ) { name = name_arg; };

 

/** dynamic safety limit. range 0 is off */

void setDynamicRange( const adlib_real range_arg = 1e12 );

 

/*************************************/

/** SETTING GAINS, ZEROS AND POLES  **/

/*************************************/

 

/** multiply gain by gain and add zeros and poles to the existing filter */

  bool addKZP

    ( const adlib_real gain = 1,

      const size_t numZeros = 0, const adlib_real *zeros = NULL,

      const size_t numPoles = 0, const adlib_real *poles = NULL,

      const size_t numZeroPairs = 0, const adlib_complex *zeroPairs = NULL,

      const size_t numPolePairs = 0, const adlib_complex *polePairs = NULL );

 

/** multiply gain by gain and add zeros and poles to the existing filter */

/** zeros and poles are specified in degree / Hz                         */

/** addKZPHz( pole, zero) = addKZP( -2 Pi pole, -2 Pi zero )             */

  bool addKZPHz

    ( const adlib_real gain = 1,

      const size_t numZeros = 0, const adlib_real *zeros = NULL,

      const size_t numPoles = 0, const adlib_real *poles = NULL,

      const size_t numZeroPairs = 0, const adlib_complex *zeroPairs = NULL,

      const size_t numPolePairs = 0, const adlib_complex *polePairs = NULL );

 

/** multiply gain by gain and add zeros and poles to the existing filter  */

/** zeros and poles are specified in degree / Hz                          */

/** complex pairs are specified by Q, instead of using a complex number   */

/** (re, im) = -2 Pi freq / ( 2 Q ) { 1, sqrt( 4 Q^2 - 1 ) }              */

/**      When Q < 0.5, pole (zero) pair becomes a simple pile (not pair)  */

/**      This is to use one expression for both a complex pole and a pole */

  bool addKZPHzQ

    ( const adlib_real gain = 1,

      const size_t numZeros = 0,

      const adlib_real *zeros = NULL, const adlib_real *zeroQs = NULL,

      const size_t numPoles = 0,

      const adlib_real *poles = NULL, const adlib_real *poleQs = NULL );

 

/** Set the gain factor */

  void setGain( adlib_real gain) { dfRec.coef[0] = gain; gainS = gain; calcAB();};

 

/** Set the gain at a given frequency */

  void setGainHz( adlib_real gain, adlib_real freq );

 

  /** Add to the zero vector */

  bool addZero( const adlib_real zero );

  bool addZeroHzQ( const adlib_real zero, const adlib_real zeroQ );

 

  /** Add to the pole vector */

  bool addPole( adlib_real pole);

  bool addPoleHzQ( const adlib_real pole, const adlib_real poleQ );

 

  /** Add to the zero pair vector */

  bool addZeroPair( adlib_complex zeroPair );

  bool addZeroPair( adlib_real zero_real, adlib_real zero_imag );

 

  /** Add to the pole pair vector */

  bool addPolePair( adlib_complex polePair );

  bool addPolePair( adlib_real pole_real, adlib_real pole_imag );

 

/**********************************************/

/** VARIOUS SPECIAL FILTERS                  **/

/** to setup the filter                      **/

/** DF aFilter;                              **/

/** aFilter.calcAB_xxx( TIME_STEP, params ); **/

/**********************************************/

 

  bool calcAB_buttap( const adlib_real delT_arg,

                const size_t order,

                const adlib_real cutoffFreq,

                const adlib_real gain_arg,

                const bool isLowPass = true );

 

  bool calcAB_cheb1ap( const adlib_real delT_arg,

                 const size_t order,

                 const adlib_real cutoffFreq,

                 const adlib_real ripple,

                 const adlib_real gain_arg,

                 const bool isLowPass = true );

 

  bool calcAB_cheb2ap( const adlib_real delT_arg,

                 const size_t order,

                 const adlib_real cutoffFreq,

                 const adlib_real ripple,

                 const adlib_real gain_arg,

                 const bool isLowPass = true );

 

  bool calcAB_elliptic( const adlib_real delT_arg,
               const size_t order,
               const adlib_real cutoffFreq,
               const adlib_real passbandRipple,
               const adlib_real stopbandRipple,
               const adlib_real gain_arg,
               const bool DCUnitGain = true,
               const bool isLowPass = true );
 

 

  bool calcAB_AntFilter( const adlib_real delT_arg,

                const adlib_real nyquestLow,

                const adlib_real nyquestHigh );

 

/*** How to use calcAB_XXX in FUNC_X ***/

 

in MemberDecl

 

DF cheby;
DF butter;
DF elliptic;

 

in Constructor

 

adlib_real gain = 100;
adlib_real cutHz = 10;
adlib_real pR = 0.5;
adlib_real sR = 20;

cheby.calcAB_cheb1ap( TIME_STEP, 4, cutHz, pR, gain );
butter.calcAB_buttap(TIME_STEP, 4, cutHz, gain );
elliptic.calcAB_elliptic(TIME_STEP, 6, cutHz, pR, sR, gain );
 

 

in Equation

 

out0 = cheby.filterApply(in0);
out1 = butter.filterApply(in0);
out2 = elliptic6.filterApply(in0);