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

/**         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 **/

/** 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 */

( 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 )             */

( 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 */

( 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 */

/** Add to the pole vector */

/** Add to the zero pair vector */

/** Add to the pole pair vector */

/** 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 bool isLowPass = true );

bool calcAB_cheb1ap( const adlib_real delT_arg,

const size_t order,

const bool isLowPass = true );

bool calcAB_cheb2ap( const adlib_real delT_arg,

const size_t order,

const bool isLowPass = true );

bool calcAB_elliptic( const adlib_real delT_arg,
const size_t order,
const bool DCUnitGain = true,
const bool isLowPass = true );

bool calcAB_AntFilter( const adlib_real delT_arg,

const adlib_real nyquestHigh );

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

in MemberDecl

DF cheby;
DF butter;
DF elliptic;

in Constructor

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);