⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 simulatedsm.c

📁 高阶sigma-delta调制器设计matlab工具包, 半波带滤波器设计工具包
💻 C
字号:
/* simulateDSM.c - A MEX-file for simulating a delta-sigma modulator %[v,xn,xmax,y] = simulateDSM( u, ABCD, nlev[2], x0[0] )% or%[v,xn,xmax,y] = simulateDSM( u, ntf, nlev[2], x0[0] )%%Compute the output of a general delta-sigma modulator with input u,%a structure described by ABCD, an initial state x0 (default zero) and %a quantizer with a number of levels specified by nlev.%Multiple quantizers are implied by making nlev an array,% and multiple inputs are implied by the number of rows in u.%%Alternatively, the modulator may be described by an NTF.%The NTF is zpk object. (The STF is assumed to be 1.)%The structure that is simulated is the block-diagional structure used by%zp2ss.m.%%The obsolete NTF style is %a struct with fields 'zeros' and 'poles' ('k' is assumed to be 1).%the STF is assumed to be 1.%The structure that is simulated is the block-diagional structure used by%zp2ss.m.*/#include <stdio.h>#include <math.h>#include "mex.h"/* Global variables *//* In an effort to make the code more readable and to cut down on the overhead    associated with function calls, I have made many variables global. */char *cmdName = "simulateDSM";int    order,	/* The order of the modulator. */    nu,		/* The number of inputs, inferred from size(u,1). */    nq,		/* The number of quantizers, inferred from nlev */    N,		/* The number of time steps. */    ABCD_rows,	/* The number of rows in ABCD */    saveState;	/* Flag: keep track of the states. */double     *u,		/* Points into the input array. */    *v,		/* Points into the output array. */    *x,		/* The current state. */    *xn,	/* Points (in)to the (output) state array. */    *xMax,	/* Points to the state maxima output array. */    *py,	/* Points to the quantizer input output array. */    *ABCD,	/* The ABCD array (col-wise) description of the moduator. */    *nlev,	/* The number of quantizer levels. */    default_nlev=2;#ifdef __STDC__double quantize(double yy, int nLevels)#elsedouble quantize(yy, nLevels)double yy;int nLevels;#endif{     double vv;    if(nLevels%2) { /* Mid-tread quantizer */	vv = 2*floor(0.5*(yy+1));	if( vv > nLevels )	    vv = nLevels-1;	else if( vv < -nLevels )	    vv = 1-nLevels;    }    else { /* Mid-rise quantizer */	vv = 2*floor(0.5*yy)+1;	if( vv > nLevels )	    vv = nLevels-1;	else if( vv < -nLevels )	    vv = 1-nLevels;    }    return vv;}/* The following function is for debugging purposes only */#ifdef __STDC__void printMatrix(double *x, int m, int n)#elseprintMatrix(x, m, n)double *x;int m, n;#endif{int i,j;for(i=0; i<m; ++i){    for(j=0; j<n; ++j)	mexPrintf("%8.3f ",x[i+m*j]);    mexPrintf("\n");    }}#ifdef __STDC__void fatalError(char *s)#elsefatalError(s)char *s;#endif{    char msg[1024];    sprintf(msg, "%s: %s", cmdName, s);    mexErrMsgTxt(msg);}#ifdef __STDC__void initializeX(const mxArray *M_x0)#elseinitializeX(M_x0)mxArray *M_x0;#endif{    int i;    double *x0 = mxGetPr(M_x0);    if( mxGetM(M_x0)!=order || mxGetN(M_x0)!=1 )	fatalError("x0 must be an order x 1 column vector.");    for(i=0; i<order; ++i)	x[i] = *x0++;}#ifdef __STDC__void checkArgs(int nlhs, mxArray **plhs, int nrhs, const mxArray **prhs)#elsecheckArgs(nlhs, plhs, nrhs, prhs)int nlhs, nrhs;mxArray *plhs[], *prhs[];#endif{    int i;    int form;    double *pABCD;    const mxArray *arg2=prhs[1];    mxArray *zeros, *poles;    /* Verify the rhs (input) arguments */    if( nrhs < 2 )	fatalError("At least two input arguments are needed.");    if( !mxIsDouble(prhs[0]) )	fatalError("The input vector does not contain double-precision data.");    u = mxGetPr(prhs[0]);    nu = mxGetM(prhs[0]);    N = mxGetN(prhs[0]);    nq = 1;    nlev = &default_nlev;    if(nrhs>=3)	if( !( mxIsEmpty(prhs[2]) || mxIsNaN(*mxGetPr(prhs[2])) ) ){	    nq = mxGetM(prhs[2]) * mxGetN(prhs[2]);	    nlev = mxGetPr(prhs[2]);	}    /* Determine the form of the modulator */    if( mxIsClass(arg2,"zpk") ){		/* NTF in zpk form */	form = 0;	if( (zeros=mxGetCell(mxGetField(arg2,0,"z"),0)) == 0 )	    fatalError("No z field in the NTF object.");	if( !mxIsNumeric(zeros) )	    fatalError("The zeros field is not numeric.");	if( (poles=mxGetCell(mxGetField(arg2,0,"p"),0)) == 0 )	    fatalError("No p field in the NTF object.");	if( (order=mxGetNumberOfElements(zeros)) != mxGetNumberOfElements(poles) )	    fatalError("The number of poles must equal the number of zeros.");    }    else if( mxIsStruct(arg2) ){		/* Obsolete NTF form */	if( (zeros=mxGetField(arg2,0,"zeros"))==0 )	    fatalError("No zeros field in the NTF struct.");	if( !mxIsNumeric(zeros) )	    fatalError("The zeros field is not numeric.");	if( (poles=mxGetField(arg2,0,"poles"))==0 )	    fatalError("No poles field in the NTF struct.");	if( !mxIsNumeric(poles) )	    fatalError("The poles field is not numeric.");	if( (order=mxGetNumberOfElements(zeros)) != mxGetNumberOfElements(poles) )	    fatalError("The number of poles must equal the number of zeros.");	mexWarnMsgTxt("You appear to be using an old-style form of NTF specification.\nAutomatic converstion to the new form will be done for this release only.");	form = 2;    }    else if( mxIsNumeric(arg2) ){	if( mxGetN(arg2)==mxGetM(arg2)+nu && mxIsDouble(arg2) ){	    form = 1;			/* ABCD form */	    order = mxGetM(arg2)-nq;	}	else if( mxGetN(arg2)==2 ){	    mexWarnMsgTxt("You appear to be using the old-style form of NTF specification.\nAutomatic converstion to the new form will be done for this release only.");	    form = 3;		/* old NTF form */	    order = mxGetM(arg2);	}	else	    fatalError("ABCD must be an order+nq by order+nu+nq matrix.");    }    else	fatalError("The second argument is neither a proper ABCD matrix nor an NTF.");    if( form==1 ){		/* ABCD form */	ABCD = mxGetPr(arg2);    }    else if( form==0 || form==2 || form==3 ){	/* NTF form */	/* MATLAB code for computing ABCD 	   [A,B2,C,D2] = zp2ss(ntf.poles,ntf.zeros,-1);	   D2 = 0;	   % !!!! Assume stf=1	   B1 = -B2;	   D1 = 1;	   ABCD = [ A B1 B2; C D1 D2]	*/	mxArray *lhs[4],*pntf[3];	double *p1,*p2;	if( nu != 1 )	    fatalError("Fatal error. Number of inputs must be 1 for a modulator specified by its NTF\n");	if( nq != 1)	    fatalError("Fatal error. Number of quantizers must be 1 for a modulator specified by its NTF\n");	/* Copy the ntf (arg2) into the temporary pntf[] matrices. */	/* This could be accomplished more efficiently (but more dangerously)	   by directly setting the elements of the mxArray data structure. */	pntf[0] = mxCreateDoubleMatrix(order,1,mxCOMPLEX);	pntf[1] = mxCreateDoubleMatrix(order,1,mxCOMPLEX);	pntf[2] = mxCreateDoubleMatrix(1,1,mxREAL);	p2 = mxGetPr((form==0||form==2) ? zeros:arg2);	for( p1=mxGetPr(pntf[1]), i=0; i<order; ++i)	    *p1++ = *p2++;	if( form!=3 )	    p2 = mxGetPr(poles);	for( p1=mxGetPr(pntf[0]), i=0; i<order; ++i)	    *p1++ = *p2++;	p2 = mxGetPi((form==0||form==2) ? zeros:arg2);	if( p2 ) /* Non-null imaginary part. */	    for( p1=mxGetPi(pntf[1]),  i=0; i<order; ++i)		*p1++ = *p2++;	if( form!=3 )	    p2 = mxGetPi(poles);	if( p2 ) /* Non-null imaginary part. */	    for( p1=mxGetPi(pntf[0]), i=0; i<order; ++i)		*p1++ = *p2++;	*mxGetPr(pntf[2]) = -1;	mexCallMATLAB(4,lhs,3,pntf,"zp2ss"); 	p1 = mxGetPr(lhs[0]);	p2 = mxGetPr(lhs[2]);	ABCD = (double *)mxCalloc((order+nu)*(order+nu+nq),sizeof(double));	pABCD = ABCD;	for( i=0; i<order; ++i ){	    int j;	    for( j=0; j<order; ++j )		*pABCD++ = *p1++;	    *pABCD++ = *p2++;	}	p1 = mxGetPr(lhs[1]);	/* B1 = -B2 */	for( i=0; i<order; ++i )	    *pABCD++ = -*p1++;	*pABCD++ = 1;		/* D1 */	p1 = mxGetPr(lhs[1]);	/* B2 */	for( i=0; i<order; ++i )	    *pABCD++ = *p1++;	*pABCD = 0;		/* D2 */	for(i=0;i<4;++i) 	    mxDestroyArray(lhs[i]);	for(i=0;i<2;++i) 	    mxDestroyArray(pntf[i]);    }    else	fatalError("Internal error. form != 0, 1, 2 or 3!");    ABCD_rows = order + nq;    plhs[0] = mxCreateDoubleMatrix(nq,N,mxREAL);    v = mxGetPr(plhs[0]);    x = (double *)mxCalloc(order,sizeof(double));    if(nrhs>=4){	if( !( mxIsEmpty(prhs[3]) || mxIsNaN(*mxGetPr(prhs[3])) ) )		    initializeX(prhs[3]);	}        /* Verify the lhs (output) arguments */    saveState=0;     py=0;    xMax=0;    switch(nlhs){	case 4:	    plhs[3] = mxCreateDoubleMatrix(nq,N,mxREAL);	    py = mxGetPr(plhs[3]);	case 3:	    plhs[2] = mxCreateDoubleMatrix(order,1,mxREAL);	    xMax = mxGetPr(plhs[2]);	case 2:	    plhs[1] = mxCreateDoubleMatrix(order,N,mxREAL);	    xn = mxGetPr(plhs[1]);	    saveState=1;	    break;	case 1:	    break;	default:	    fatalError("Incorrect number of output arguments.");    }    if( !saveState )	xn = (double *)mxCalloc(order,sizeof(double));}/* Simulate the modulator using the difference equations. *//* For efficiency, store the state in xn and compute from x. *//* (These variables may be recycled internally, depending   on the output variables requested.) */#ifdef __STDC__void simulateDSM()#elsesimulateDSM()#endif{    int i,j,t, qi;    double *pABCD, *ptr, *pxn, tmp;    for( t=0; t<N; ++t ){ /* [xn;y] = ABCD*[x;u;v]; x=xn;*/	/* Compute y = C*x + D1*u and thence v for each quantizer */	for( qi=0; qi<nq; ++qi){	    tmp = 0;	    for(i=0, pABCD=ABCD+order+qi, ptr=x; i<order; ++i, pABCD+=ABCD_rows)		tmp += (*pABCD) * *ptr++;	    for(i=0, ptr=u; i<nu; ++i, pABCD+=ABCD_rows)		tmp += (*pABCD) * *ptr++;	    if( py!=0 )		*py++ = tmp;	    v[qi] = quantize(tmp, nlev[qi]);	}	/* Next compute xn = A*x + B*[u;v], */	for( i=0, pxn=xn; i<order; ++i ){	    tmp=0;	    pABCD=ABCD+i;	    for( ptr=x, j=0; j<order; ++j, pABCD += ABCD_rows )		tmp += *pABCD * *ptr++;	    for( ptr=u, j=0; j<nu; ++j, pABCD += ABCD_rows )		tmp += *pABCD * *ptr++;	    for( ptr=v, j=0; j<nq; ++j, pABCD += ABCD_rows )		tmp += *pABCD * *ptr++;	    *pxn++ = tmp;	    }	u += nu;	v += nq;	if(xMax!=0){	    for( i=0; i<order; ++i){		double abs=fabs(xn[i]);		if( abs > xMax[i] )		    xMax[i] = abs;	    }	}	if(saveState){	    x = xn;	    xn += order;	}	else { /* swap x and xn */	    double *xtmp = x;	    x = xn;	    xn = xtmp;	} /* if(saveState) */    } /* for( t=0 .... ) */}#ifdef __STDC__void mexFunction(int nlhs, mxArray **plhs, int nrhs, const mxArray **prhs)#elsemexFunction(nlhs, plhs, nrhs, prhs)int nlhs, nrhs;mxArray *plhs[], *prhs[];#endif{    checkArgs(nlhs, plhs, nrhs, prhs);    /* Print the variables being used     mexPrintf("x=\n");		printMatrix(x,order,1);    mexPrintf("\nABCD=\n");	printMatrix(ABCD,order+nq,order+nu+nq);    */    simulateDSM();}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -