%% $RCSfile: sdspupfirdn2.tlc,v $ %% $Revision: 1.2 $ $Date: 1999/10/22 15:36:52 $ %% %% Dale Shpak, Steve Conahan %% Copyright (c) 1995-1999 The MathWorks, Inc. %% %% Abstract: FIR Integer-Ratio Sample-Rate Conversion %% %implements sdspupfirdn2 "C" %include "dsplib.tlc" %% Function: BlockInstanceSetup =============================================== %% %% Abstract: %% Rename the S-Function parameters for easy reference. %% %function BlockInstanceSetup(block, system) void %assign INPORT = 0 %assign OUTPORT = 0 %assign INPORTWIDTH = LibDataInputPortWidth(INPORT) %assign OUTPORTWIDTH = LibDataOutputPortWidth(OUTPORT) %% DWorks: InPhaseIdx, OutIdx, MemIdx, PartialSums, DiscState, OutBuf %% %assign IN_PHASE_IDX = block.DWork[0] %assign OUT_IDX = block.DWork[1] %assign MEM_IDX = block.DWork[2] %assign SUMS = block.DWork[3] %assign STATES = block.DWork[4] %assign OUT_BUFF = block.DWork[5] %% OUT_BUFF needed only if (n1 > 0) %assign CFF_BASE = 0 %assign CFF_PTR = 1 %assign IFACTOR = SFcnParamSettings.IFACTOR %assign DFACTOR = SFcnParamSettings.DFACTOR %assign LENGTH = SIZE(SFcnParamSettings.FILTER,1) %assign NCOLS = IFACTOR * DFACTOR %assign NROWS = LENGTH / NCOLS %assign SUB_ORDER = LENGTH / NCOLS %assign NSTATES = LibBlockDWorkWidth(STATES) %assign FILTER = SFcnParamSettings.FILTER %assign FILT_COMPLEX = TYPE(SFcnParamSettings.FILTER[0]) == "Complex" %assign DATA_COMPLEX = LibBlockInputSignalIsComplex(INPORT) %assign OUT_COMPLEX = (FILT_COMPLEX || DATA_COMPLEX) %assign numDims = LibBlockInputSignalNumDimensions(INPORT) %assign dims = LibBlockInputSignalDimensions(INPORT) %assign COLS = (numDims == 2) ? dims[1] : 1 %assign ROWS = dims[0] %assign FRAMEBASED = LibBlockInputSignalIsFrameData(INPORT) %assign FRAME = FRAMEBASED ? ROWS : 1 %assign NUM_CHANS = FRAMEBASED ? COLS : INPORTWIDTH %assign MEM_SIZE = NSTATES / NUM_CHANS %assign N0 = SFcnParamSettings.N0 %assign N1 = SFcnParamSettings.N1 %assign MEM_STRIDE = MEM_SIZE - N0 %assign OUT_LEN = N1 * IFACTOR %assign DAT_T = DATA_COMPLEX ? "creal_T" : "real_T" %assign FILT_T = FILT_COMPLEX ? "creal_T" : "real_T" %assign OUT_T = OUT_COMPLEX ? "creal_T" : "real_T" %assign block = block + INPORT + OUTPORT + INPORTWIDTH + OUTPORTWIDTH\ + IN_PHASE_IDX + OUT_IDX + MEM_IDX + SUMS + STATES\ + OUT_BUFF + CFF_BASE + CFF_PTR + IFACTOR + DFACTOR\ + LENGTH + NCOLS + NROWS + SUB_ORDER + NSTATES\ + FILTER + FILT_COMPLEX + DATA_COMPLEX + OUT_COMPLEX\ + NUM_CHANS + FRAME + MEM_SIZE + N0 \ + N1 + MEM_STRIDE + OUT_LEN + DAT_T\ + FILT_T + OUT_T %endfunction %% BlockInstanceSetup %% Function: InitializeConditions ============================================= %% %% Abstract: %% Initialize the DWork vector (Buffer) to the initial values specified. %% %function InitializeConditions(block, system) Output /* DSP Blockset FIR Rate Conversion % (%) - % */ { %% %% We do not support discontiguous inputs %% %assign CONTIG = IsInputPortContiguous(block,INPORT) %if (!CONTIG) LibDiscontiguousInputError(block) %endif %% %% Note: ICs are only needed if n1 > 0 %% %assign IC = SFcnParamSettings.IC %assign IC_ROWS = % %assign IC_COLS = % %assign NUM_IC = SIZE(SFcnParamSettings.IC,1) %assign IC_CPLX = TYPE(SFcnParamSettings.IC[0]) == "Complex" %assign IC_T = IC_CPLX ? "creal_T" : "real_T" %% /* Filter coefficients */ static % \ %if (N1 > 0) %if (NUM_IC > 1) /* Block initial conditions definition */ Static % \ %endif %% (NUM_IC > 1) /* Initialize the internal buffers with block initial conditions */ %% %% The ICs must be filled in according to the OUTPORTWIDTH %% { int i; %% %% Note: The ICs are passed into the RTW file from the C S-fcn as %% COMPLEX no matter what they really are. This is corrected here. %% %assign IC_DTYPE = (FILT_COMPLEX || DATA_COMPLEX) ? "creal_T" : "real_T" % *outBuff = %; for (i=0; i<%; i++) { %% %if (NUM_IC <= 1) %% /* Scalar IC */ %if NUM_IC == 0 %assign IC_re = 0.0 %assign IC_im = 0.0 %else %assign IC_re = REAL(IC[0]) %if !IC_CPLX %assign IC_im = 0.0 %else %assign IC_im = IMAG(IC[0]) %endif %endif %if !(FILT_COMPLEX || DATA_COMPLEX) *outBuff++ = %; %else outBuff->re = %; (outBuff++)->im = %; %endif %else %% %% We are not using memcopy here because if the input %% is complex and the ic is real, we fill in the imaginary %% part with zeros. %% /* Vector IC */ %if !(FILT_COMPLEX || DATA_COMPLEX) *outBuff++ = ic[i]; %else outBuff->re = %<(IC_CPLX) ? "ic[i].re" : "ic[i]">; (outBuff++)->im = %<(IC_CPLX) ? "ic[i].im" : 0.0>; %endif %endif } %% end for outBuffWidth } %% END initialize internal buffers %endif %% (N1>0) /* * Initialize the counters and pointers. */ % = % = % = 0; % = % = filter; } %endfunction %% Function: Outputs ========================================================== %% %function Outputs(block, system) Output /* DSP Blockset FIR Rate Conversion % (%) - % */ { % *x = %; % *tap0 = %; % *sums = %; % *outBuff = %; % *y = %; % *cff; int_T mIdx; int_T oIdx; int_T inIdx; const real_T outSigNormScaling = 1.0 / ( (real_T) % ); %roll sigIdx1 = [ 0:% ], lcv1 = 2, block, "InlineRoller" /* Each channel uses the same filter phase but accesses * its own state memory and input. */ inIdx = %; mIdx = %; oIdx = %; cff = %; %roll sigIdx2 = [ 0:% ], lcv2 = 2, block, "InlineRoller" *(tap0+mIdx) = *x++; { /* Compute partial sums for each interpolation phase */ %roll sigIdx3 = [ 0:% ], lcv3 = 2, block, "InlineRoller" % *tap = tap0 + mIdx - ( (%-%) * % ); % *stop; int_T m; while (tap < tap0) tap += %; stop = tap - %; if (stop < tap0) stop += %; /* * Perform the convolution for this phase (on every dFactor samples) * until we reach the start of the (linear) state memory */ m = 0; tap += %; %if (DATA_COMPLEX) %if (FILT_COMPLEX) while ( ((tap -= %) >= tap0) && (++m <= %) ) { sums[%].re += (tap->re) * (cff->re) - (tap->im) * (cff->im); sums[%].im += (tap->im) * (cff->re) + (tap->re) * (cff->im); ++cff; } /* wrap the state memory pointer to the next element */ tap += %; /* Finish the convolution for this phase */ while (++m <= %) { tap -= %; sums[%].re += (tap->re) * (cff->re) - (tap->im) * (cff->im); sums[%].im += (tap->im) * (cff->re) + (tap->re) * (cff->im); ++cff; } %else while ( ((tap -= %) >= tap0) && (++m <= %) ) { sums[%].re += (tap->re) * (*cff ); sums[%].im += (tap->im) * (*cff++); } /* wrap the state memory pointer to the next element */ tap += %; /* Finish the convolution for this phase */ while (++m <= %) { sums[%].re += (tap-=%)->re * (*cff); sums[%].im += (tap->im) * (*cff++); } %endif %else %% Real data %if (FILT_COMPLEX) while ( ((tap -= %) >= tap0) && (++m <= %) ) { sums[%].re += (*tap) * cff->re; sums[%].im += (*tap) * (cff++)->im; } /* wrap the state memory pointer to the next element */ tap += %; /* Finish the convolution for this phase */ while (++m <= %) { sums[%].re += *(tap -= %) * cff->re; sums[%].im += (*tap) * (cff++)->im; } %else while ( ((tap -= %) >= tap0) && (++m <= %) ) { sums[%] += (*tap) * (*cff++); } /* wrap the state memory pointer to the next element */ tap += %; /* Finish the convolution for this phase */ while (++m <= %) { sums[%] += *(tap -= %) * (*cff++); } %endif %endif %endroll %% IFACTOR } /* Output and update the counters modulo their buffer size */ if (++inIdx == %) { %roll sigIdx4 = [ 0:% ], lcv4 = 2, block, "InlineRoller" /* Put values in their appropriate locations in the output buffer */ int_T itmp = (%*%+oIdx); while (itmp >= %) itmp -= %; outBuff[itmp] = sums[%]; itmp = %+oIdx; while (itmp >= %) itmp -= %; %if (!OUT_COMPLEX) /* Output the current samples, NORMALIZED by the Interpolation */ /* Factor in order to preserve input signal scaling. Note that */ /* this is done here once at the end of the computation (i.e. */ /* just before the output gets sent out) in order to preserve */ /* as much signal numerical precision as possible. */ *y++ = outBuff[itmp] * outSigNormScaling; sums[%] = 0.0; %else { /* Output the current samples, NORMALIZED by the Interpolation */ /* Factor in order to preserve input signal scaling. Note that */ /* this is done here once at the end of the computation (i.e. */ /* just before the output gets sent out) in order to preserve */ /* as much signal numerical precision as possible. */ creal_T normCplxOutput; real_T normRealOutput; real_T normImagOutput; normCplxOutput = outBuff[itmp]; /* not normalized yet */ normRealOutput = normCplxOutput.re * outSigNormScaling; normCplxOutput.re = normRealOutput; normImagOutput = normCplxOutput.im * outSigNormScaling; normCplxOutput.im = normImagOutput; *y++ = normCplxOutput; } sums[%].re = sums[%].im = 0.0; %endif %% OUT_COMPLEX %endroll if ( (oIdx += %) >= % ) oIdx = 0; inIdx = 0; cff = %; } if (++mIdx >= %) mIdx = 0; %endroll %% FRAME %if (NUM_CHANS > 1) sums += %; tap0 += %; outBuff += %; %endif %endroll %% CHANNEL /* Update stored indices for next time */ % = inIdx; % = mIdx; % = oIdx; % = cff; } %endfunction %% [EOF] sdspupfirdn2.tlc