%% $RCSfile: sdspsine2.tlc,v $ %% $Revision: 1.6 $ $Date: 2000/08/21 21:35:07 $ %% %% Abstract: DSP Blockset sine wave source block %% %% Copyright 1995-2000 The MathWorks, Inc. %% %implements sdspsine2 "C" %% Function: BlockTypeSetup =============================================== %% %function BlockTypeSetup(block, system) Output %% Cache 2*pi as a #define statement: %% % %endfunction %% BlockTypeSetup %% Function: BlockInstanceSetup =============================================== %% %function BlockInstanceSetup(block, system) void %% %assign OUTPORT = 0 %assign IS_COMPLEX = CAST("Boolean",(SFcnParamSettings.OutputType == "Complex")) %assign dType = (IS_COMPLEX) ? "creal_T *" : "real_T *" %assign isPeriodic = CAST("Boolean",(SFcnParamSettings.isPeriodic == "Yes")) %assign isTableWithAmpEncoded = CAST("Boolean",(SFcnParamSettings.isTableWithAmpEncoded == "Yes")) %assign outWidth = LibBlockOutputSignalWidth(OUTPORT) %assign isDiscrete = CAST("Boolean",(SFcnParamSettings.SampleMode == "Discrete")) %assign nSamps = (isDiscrete) ? SFcnParamSettings.FrameLength : 1 %assign nChans = outWidth / nSamps %assign scalarY = (nSamps * nChans == 1) %% %assign block = block + OUTPORT + IS_COMPLEX + dType + isPeriodic + isTableWithAmpEncoded ... + outWidth + nSamps + nChans + scalarY + isDiscrete %assign InlineParams = (InlineParameters != 0) %assign block = block + InlineParams %% %endfunction %% BlockInstanceSetup %% Function: InitializeConditions ============================================= %% %function InitializeConditions(block, system) Output %% %if (isDiscrete) /* DSP Blockset Sine Wave (%) - % - Initialize */ %% %if SFcnParamSettings.CompMethod == "Differential" %% /* Discrete differential mode: */ %if SFcnParamSettings.ResetState == "Reset" % %else % %endif %% %elseif SFcnParamSettings.CompMethod == "TrigFcn" %% %% %if isPeriodic %% /* Discrete periodic trigonometric mode: */ %if SFcnParamSettings.ResetState == "Reset" /* Restart at time zero: */ %if nChans==1 % = (uint16_T)0; %else memset(%, 0, %*sizeof(uint16_T)); %endif %% %else %% Catchup Mode %% /* Catch-up to simulation time: */ { const real_T Ts = %; %if freqIncr real_T *freq = (real_T *)%; %else const uint16_T iSpP = (uint16_T)((1.0 / (% Ts)) + .5); %endif %% %if nChans > 1 %% multiple channels %% uint16_T *count = %; int_T i; for (i=0; i < %; i++) { %if freqIncr const uint16_T iSpP = (uint16_T)((1.0 / (% Ts)) + .5); %endif *count++ = (uint16_T)((uint32_T)(% / Ts + 0.5) % iSpP); } %% end of channel loop %% %else %% single channel %% % = (uint16_T)((uint32_T)(% / Ts + 0.5) % iSpP); %endif } %endif %else %% non-periodic discrete trig mode %% /* Discrete aperiodic trigonometric mode: */ %if SFcnParamSettings.ResetState == "Reset" /* Restart at time zero: */ % = (uint32_T)0; %else { /* Catch-up to simulation time: */ %% %% We want the cast to uint32 to always truncate for the count because %% LibGetT() will give return a time that is some fraction later than %% the actual time of this task. (critical in multi-tasking mode) %% Note the difference between this and the CMEX which uses ssGetSampleTime(S,0) %% because it has access to the tid, which the RTW mdlInit does not. %% const real_T Ts = %; % = (uint32_T)((% / Ts) + 0.5); } %endif %endif %% isPeriodic loop %% %elseif SFcnParamSettings.CompMethod == "TableLookup" %% %assign numCombos = SFcnParamSettings.numCombos %% /* Table lookup: */ %if SFcnParamSettings.ResetState == "Reset" /* Restart at time zero: */ %if numCombos == 1 % = 0; %else memset(%, 0, %*sizeof(uint16_T)); %endif %else /* Catch up to simulation time: */ { const real_T Ts = %; %if numCombos > 1 int_T i; for (i=0; i<%; i++) { % = (uint16_T)((uint32_T)(% / Ts + 0.5) % %); } %else % = (uint16_T)((uint32_T)(% / Ts + 0.5) % %); %endif } %endif %% %endif %% CompMethod loop %endif %% Discrete loop %endfunction %% InitializeConditions %% Function: Outputs ========================================================== %% %function Outputs(block, system) Output /* DSP Blockset Sine Wave (%) - % - Output */ %% %if (SFcnParamSettings.CompMethod != "Differential") %\ %endif %if (isDiscrete) %if SFcnParamSettings.CompMethod == "TrigFcn" %if % %% % %% %else %% % %% %endif %elseif SFcnParamSettings.CompMethod == "TableLookup" %% % %% %else %% % %% %endif %else %% % %% %endif %endfunction %% Outputs %% Function: DiscreteTrig ===================================================== %% %function DiscreteTrig(block) Output %% %assign Ts = LibBlockSampleTime(block) / nSamps %assign Ts_pi2 = SFcnParamSettings.Pi2 * Ts { /* Discrete aperiodic trigonometric mode: */ const real_T Ts_pi2 = %; %% %if ampIncr real_T *amp = (real_T *)%; %endif %if freqIncr real_T *freq = (real_T *)%; %endif %if phaseIncr real_T *phase = (real_T *)%; %endif %% %if !scalarY %if (nChans > 1) %if (nSamps == 1) %assign Ystr = "%" %assign Ystr_re = "%.re" %assign Ystr_im = "%.im" %else %y = (%)%; %assign Ystr = "*y++" %assign Ystr_re = "y->re" %assign Ystr_im = "(y++)->im" %% %endif %else %% Only to be used when nSamps > 1 when nChans == 1 %% If nSamps==1, another special case is used that ignores these assignments: %assign Ystr = "%" %assign Ystr_re = "%.re" %assign Ystr_im = "%.im" %endif %endif %% %if nSamps > 1 %% multiple samples per frame %if nChans > 1 uint32_T cnt; /* Copy counter for time update */ %else %% multiple samples per frame, but only one channel: uint32_T cnt = %; /* Reset the counter */ %endif %endif %% %if nChans > 1 int_T i; /* Loop over each channel: */ for (i = 0; i < %; i++) { %endif %% const real_T Ts_pi2_f = % Ts_pi2; %if (nChans > 1 && nSamps > 1 && ampIncr) real_T ampVal = *amp; %endif %% %if nSamps > 1 %% Frame loop int_T j; %if nChans > 1 %% multiple channels, multiple samples per frame: cnt = %; /* Reset the counter */ %endif %% %% Construct argument to the cos/sin functions: %% %assign argstr = "(cnt++) * Ts_pi2_f " + phasestr_cos /* Loop over frame: */ for (j=0; j < %; j++) { %else %% No frame loop %% %% Construct argument to the cos/sin functions: %% %if nChans==1 %% If there's no frame loop, AND only 1 channel, update %% the counter in-place: %assign argstr = "%++ * Ts_pi2_f " + phasestr_cos %else %assign argstr = "% * Ts_pi2_f " + phasestr_cos %endif %endif %% %if IS_COMPLEX const real_T arg = %; %if scalarY %.re = % cos(arg); %.im = % sin(arg); %else % = % cos(arg); % = % sin(arg); %endif %else %if scalarY % = % sin(%); %else % = % sin(%); %endif %endif %% %if nSamps > 1 } %% end of frame loop %endif %% %if nChans > 1 /* Next channel parameters */ %if ampIncr amp++; %endif %if freqIncr freq++; %endif %if phaseIncr phase++; %endif %% } %% end of channel loop %endif %if nSamps > 1 % = cnt; /* Update to new count */ %else %% If there's no frame loop, we update the counter here %% However, if there's only 1 channel, we updated the counter "in place", %% so don't do it again! %if nChans>1 %++; /* Update to new count */ %endif %endif } %endfunction %% DiscreteTrig %% Function: DiscreteTrigPeriodic ============================================= %% %function DiscreteTrigPeriodic(block) Output %% %assign Ts = LibBlockSampleTime(block) / nSamps %assign Ts_pi2 = SFcnParamSettings.Pi2 * Ts { /* Discrete periodic trigonometric mode: * Uses a separate counter for each frequency to be generated, * resetting it after each period. */ %if !InlineParams const real_T Ts = %; const real_T Ts_pi2 = %; %endif %% %if !scalarY uint16_T *count = %; %y = (%)%; %endif %% %if ampIncr real_T *amp = (real_T *)%; %endif %if freqIncr real_T *freq = (real_T *)%; %endif %if phaseIncr real_T *phase = (real_T *)%; %endif %% %if nChans > 1 int_T i; /* Loop over each channel: */ for (i = 0; i < %; i++) { %endif %% %if InlineParams const real_T Ts_pi2_f = % %; const int16_T iSpP = (int16_T)((1.0 / (% %)) + 0.5); %else const real_T Ts_pi2_f = % Ts_pi2; const int16_T iSpP = (int16_T)((1.0 / (% Ts)) + 0.5); %endif %% %if nSamps > 1 int_T j; /* Loop over frame: */ for (j=0; j < %; j++) { %endif %% %% Construct argument to the cos/sin functions: %if scalarY %assign argstr = "(%++) * Ts_pi2_f " + phasestr_cos %else %assign argstr = "(*count)++ * Ts_pi2_f " + phasestr_cos %endif %% %if IS_COMPLEX const real_T arg = %; %if scalarY %.re = % cos(arg); %.im = % sin(arg); %else y->re = % cos(arg); (y++)->im = % sin(arg); %endif %else %if scalarY % = % sin(%); %else *y++ = % sin(%); %endif %endif %% %if !scalarY if (*count >= iSpP) *count = 0; /* Update new count */ %else if (% >= iSpP) % = 0; /* Update new count */ %endif %if nSamps > 1 } %% end of frame loop %endif %% %if nChans > 1 count++; /* Next channel parameters */ %if ampIncr amp++; %endif %if freqIncr freq++; %endif %if phaseIncr phase++; %endif %% } %% end of channel loop %endif } %endfunction %% DiscreteTrigPeriodic %% Function: TableLookup ===================================================== %% %function TableLookup(block) Output %assign numCombos = SFcnParamSettings.numCombos %assign AmpEncoded = (isTableWithAmpEncoded == 1) { /* Table lookup mode: */ %if (nChans > 1) && AmpEncoded %table = (%)%; %endif %% %if !scalarY %if nChans > 1 %y = (%)%; %assign Ystr = "*y++" %assign Ystr_re = "y->re" %assign Ystr_im = "(y++)->im" %else %% Only to be used when nSamps > 1 when nChans == 1 %% If nSamps==1, another special case is used that ignores these assignments: %assign Ystr = "%" %assign Ystr_re = "%.re" %assign Ystr_im = "%.im" %endif %% %if nChans > 1 uint16_T *tableOffsets = %; %assign tableOffsets_str = "*tableOffsets" %else %assign tableOffsets_str = LibBlockDWork(TableIdx,"","",0) %endif %else %assign tableOffsets_str = LibBlockDWork(TableIdx,"","",0) %endif %% %if !AmpEncoded const uint16_T orig_offset = %; %% %% amp must be a vector if it is not encoded %% therefore nChans must be > 1 %% real_T *amp = (real_T *)%; %% int_T i; for (i=0; i++ < %; ) { /* Loop over each combination of freq/phase/amplitude */ %if nSamps > 1 int_T j; for (j=0; j++ < %;) { %endif %% %if (IS_COMPLEX) y->re = % %","",0)>.re; (y++)->im = % %","",0)>.im; %else *y++ = % %","",0)>; %endif if (++(%) >= %) { % = 0; /* Increment and wrap */ } %if nSamps > 1 } %endif amp++; if (i<%) % = orig_offset; } %else %% Amplitude is encoded in the table: %% %% Special Case: %if (scalarY) %if (IS_COMPLEX) %.re = %","",0)>.re; %.im = %","",0)>.im; %else % = %","",0)>; %endif %% if (++(%) >= %) { % = 0; /* Increment and wrap */ } %% %else %if nChans > 1 %% Multiple channel case int_T i; for (i=0; i < %; i++) { %% %if nSamps > 1 %% Have multiple samples per frame: const uint16_T SpP = %; %assign SpP_str = "SpP" %else %% Single sample per frame: %assign SpP_str = LibBlockParameter(TableSpP,"i","",0) %endif %else %% Single channel case - inline the SpP reference %assign SpP_str = LibBlockParameter(TableSpP,"","",0) %endif %% %if nSamps > 1 int_T j; for (j=0; j < %; j++) { %endif %% %% %if nChans > 1 %if (IS_COMPLEX) % = table[%].re; % = table[%].im; %else % = table[%]; %endif %else %if (IS_COMPLEX) % = %","",0)>.re; % = %","",0)>.im; %else % = %","",0)>; %endif %endif if (++(%) >= %) { % = 0; /* Increment and wrap */ } %% %if nSamps > 1 } %endif %% %if nChans > 1 %% No need to increment table pointers if no other channels exist tableOffsets++; table += %; } %endif %endif %endif } %endfunction %% Function: Differential ===================================================== %% %function Differential(block) Output %% %assign amp = Amplitude.Value %assign ampIncr = LibGetNumberOfElements(amp) > 1 %assign ampscalar = LibBlockParameter(Amplitude, "", "", 0) %assign ampstr = ampIncr ? ((nSamps>1 || IS_COMPLEX) ? "ampval *" : "*amp++ *") : "% *" %assign Frequency = SFcnParamSettings.Frequency %assign Phase = SFcnParamSettings.Phase %assign freqIncr = LibGetNumberOfElements(Frequency) > 1 %assign phaseIncr = LibGetNumberOfElements(Phase) > 1 %assign istr = "" %% { %if scalarY %assign Ystr = "%" %assign Ystr_re = "%.re" %assign Ystr_im = "%.im" %else %if (nChans > 1) %if (nSamps == 1) %assign Ystr = "%" %assign Ystr_re = "%.re" %assign Ystr_im = "%.im" %else %y = (%)%; %assign Ystr = "*y++" %assign Ystr_re = "y->re" %assign Ystr_im = "(y++)->im" %endif %else %% Only to be used when nSamps > 1 when nChans == 1 %% If nSamps==1, another special case is used that ignores these assignments: %assign Ystr = "%" %assign Ystr_re = "%.re" %assign Ystr_im = "%.im" %endif %endif %if !freqIncr && !phaseIncr %% H and Phi are scalar %% This can occur when amplictude is a vector and nChans > 1 %assign hlen = 1 %assign philen = 1 %% %assign hstr = "h" %assign phistr = "phi" %else %% H and Phi are vector %assign hlen = LibGetNumberOfElements(SFcnParamSettings.H) %assign philen = LibGetNumberOfElements(SFcnParamSettings.Phi) %% %assign hstr = "h[i]" %assign phistr = "phi[i]" %endif %% /* Differential mode: */ %% % %% %if ampIncr real_T *amp = (real_T *)%; %endif %% %if nChans > 1 %assign istr = "i" int_T i; for (i = 0; i < %; i++) { %endif %% %if ((nSamps > 1 || IS_COMPLEX) && ampIncr) real_T ampval = *amp++; %endif %if (nSamps > 1) int_T j; for (j=0; j < %; j++) { %endif /* Output */ creal_T lastval; lastval.re = %", "", "%0")>; lastval.im = %", "", "%0")>; %if IS_COMPLEX %% % = % (%.re * CMULT_RE(lastval, %) - %.im * CMULT_IM(lastval, %) ); %% % = % (%.re * CMULT_IM(lastval, %) + %.im * CMULT_RE(lastval, %) ); %% %else %% % = % (%.re * CMULT_IM(lastval, %) + %.im * CMULT_RE(lastval, %) ); %endif /* Update */ %", "", "%0")> = CMULT_RE(lastval, %); %", "", "%0")> = CMULT_IM(lastval, %); %if nSamps > 1 } %endif %% %if nChans > 1 } %endif } %endfunction %% Differential %% Function: Continuous ======================================================= %% %function Continuous(block) Output %% %% Assign appropriate variables for amplitude, frequency, and phase: %if outWidth == 1 %assign y = LibBlockOutputSignal(OUTPORT, "","",0) %% /* Continuous mode: */ %% The parentheses are important for numerical precision within the simulation. %if IS_COMPLEX %.re = % cos(% (SDSPSINE_2_PI * %) %); %.im = % sin(% (SDSPSINE_2_PI * %) %); %else % = % sin(% (SDSPSINE_2_PI * %) %); %endif %% %else { /* Continuous mode: */ const real_T t = SDSPSINE_2_PI * %; %y = (%)%; %% %if ampIncr real_T *amp = (real_T *)%; %endif %if freqIncr real_T *freq = (real_T *)%; %endif %if phaseIncr real_T *phase = (real_T *)%; %endif %% %% The code: %% int_T i; for (i = 0; i < %; i++) { %if IS_COMPLEX y->re = % cos(% t %); (y++)->im = % sin(% t %); %else *y++ = % sin(% t %); %endif } } %% scalar outWidth %endif %endfunction %% Continuous %% Function: Define_H_and_PHI ================================================= %% %function Define_H_and_PHI(hlen, philen) Output %% %% H and PHI are always complex %% %assign h = SFcnParamSettings.H %assign astr = "" %% %if hlen ==1 static const creal_T h = {%,%}; %else static const creal_T h[%] = { %foreach i = hlen %assign astr = astr + "{%,%}" %if (i < hlen-1) %assign astr = astr + "," %else %assign astr = astr + "};" %endif % %assign astr = "" %endforeach %endif %% %assign phi = SFcnParamSettings.Phi %assign astr = "" %% %if philen == 1 static const creal_T phi = {%,%}; %else static const creal_T phi[%] = { %foreach i = hlen %assign astr = astr + "{%,%}" %if (i < philen-1) %assign astr = astr + "," %else %assign astr = astr + "};" %endif % %assign astr = "" %endforeach %endif %% %endfunction %% Define_H_and_PHI %% Function: Init_Diff_Restart ================================================ %% %% %function Init_Diff_Restart(block, nChans) Output %% %% Set all "LastIdx" entries in RWork to 1+i0 %% /* Restart at time zero: */ %if nChans > 1 { int i; for(i=0; i < %; i++) { %assign LastRe = LibBlockDWork(LastIdx, "i", "", "%") %assign LastIm = LibBlockDWork(LastIdx, "i", "", "%") % = 1.0; % = 0.0; } } %else %0")> = 1.0; %0")> = 0.0; %endif %% %endfunction %% Init_Diff_Restart %% Function: Init_Diff_Catchup ================================================ %% %% %function Init_Diff_Catchup(block, nChans) Output %% %% Set all "LastIdx" entries to current simulation time %% %assign Ts = LibBlockSampleTime(block) %% We want the cast to uint32 to always truncate for the samphits because %% LibGetT() will give return a time that is some fraction later than %% the actual time of this task. (critical in multi-tasking mode) %% We should use %, but the tid is not %% available to mdlInitialCondidtions. %% /* Catch up to in time: */ %if nChans > 1 %assign freqIncr = (SIZE(SFcnParamSettings.Frequency,0) * SIZE(SFcnParamSettings.Frequency,1)) > 1 %% %if freqIncr > 0 { uint32_T samphits = (uint32_T)((%+%) / %); real_T pi2t = % * samphits * %; % int i; for(i=0; i < %; i++) { %assign LastRe = LibBlockDWork(LastIdx, "i", "", "%") %assign LastIm = LibBlockDWork(LastIdx, "i", "", "%") % = cos(pi2t * Freq[i]); % = sin(pi2t * Freq[i]); } } %else { uint32_T samphits = (uint32_T)((%+%) / %); real_T arg = % * % * samphits * %; real_T cos_value = cos(arg); real_T sin_value = sin(arg); int i; for(i=0; i < %; i++) { %assign LastRe = LibBlockDWork(LastIdx, "i", "", "%") %assign LastIm = LibBlockDWork(LastIdx, "i", "", "%") % = cos_value; % = sin_value; } } %endif %% %else { uint32_T samphits = (uint32_T)((%+%) / %); real_T arg = % * % * samphits * %; %0")> = cos(arg); %0")> = sin(arg); } %endif %% %endfunction %% Init_Diff_Catchup %% Function: Define_Freq ====================================================== %% %function Define_Freq(freq_len) Output %% %assign f = SFcnParamSettings.Frequency %assign astr = "" %% static const real_T Freq[%] = { %foreach i = freq_len %assign astr = astr + "%" %if (i < freq_len-1) %assign astr = astr + "," %else %assign astr = astr + "};" %endif % %assign astr = "" %endforeach %% %endfunction %% Define_Freq %% Function: AmpFreqPhase ===================================================== %% %function AmpFreqPhase(block) void %% ++ is for framebased. %% %if (!isTableWithAmpEncoded) %assign amp = LibBlockParameter(Amplitude, "", "", 0) %assign ampIncr = (LibBlockParameterSize(Amplitude)[0] * LibBlockParameterSize(Amplitude)[1] ) > 1 %if !ampIncr %% amp is a scalar %if InlineParams && (% == 1.0) %assign ampstr_cos = " " %assign ampstr_sin = ampstr_cos %else %assign ampscalar = LibBlockParameter(Amplitude, "", "", 0) %assign ampstr_cos = "% *" %assign ampstr_sin = ampstr_cos %endif %else %if (SFcnParamSettings.CompMethod == "TrigFcn" && !isPeriodic && nChans > 1 && nSamps > 1) %assign ampstr_cos = "ampVal *" %assign ampstr_sin = " " %else %assign ampstr_cos = "(*amp) *" %assign ampstr_sin = "(*amp++) *" %endif %endif %assign block = block + amp + ampIncr + ampstr_cos + ampstr_sin %endif %if ((SFcnParamSettings.SampleMode == "Continuous") || (SFcnParamSettings.CompMethod != "TableLookup")) %assign freq = LibBlockParameter(Frequency, "", "", 0) %assign freqIncr = (LibBlockParameterSize(Frequency)[0] * LibBlockParameterSize(Frequency)[1]) > 1 %if !freqIncr %% freq is a scalar %if InlineParams && (% == 1.0) %assign freqstr_cos = "" %assign freqstr_sin = freqstr_cos %else %assign freqscalar = LibBlockParameter(Frequency, "", "", 0) %assign freqstr_cos = "% *" %assign freqstr_sin = freqstr_cos %endif %else %assign freqstr_cos = "(*freq) *" %assign freqstr_sin = "(*freq++) *" %endif %assign block = block + freqIncr + freqstr_cos + freqstr_sin %assign phase = LibBlockParameter(Phase, "", "", 0) %assign phaseIncr = (LibBlockParameterSize(Phase)[0] * LibBlockParameterSize(Phase)[1]) > 1 %if !phaseIncr %% phase is a scalar %if InlineParams && (% == 0.0) %assign phasestr_cos = " " %assign phasestr_sin = phasestr_cos %else %assign phasescalar = LibBlockParameter(Phase, "", "", 0) %assign phasestr_cos = "+ %" %assign phasestr_sin = phasestr_cos %endif %else %assign phasestr_cos = "+ (*phase)" %assign phasestr_sin = "+ (*phase++)" %endif %assign block = block + phase + phaseIncr + phasestr_cos + phasestr_sin %endif %endfunction %% AmpFreqPhase %% [EOF] sdspsine2.tlc