%implements VariableTransportDelay "C"
%include "tdelay_sup.tlc"
%function BlockTypeSetup(block, system) void
%<TDelayTypeSetup(block, system)>
%endfunction
%function Start(block, system) Output
%assign isRSIM = isRSim
{
%if (ParamSettings.Transportdelay == "yes" )
%assign isTransportdelay = TLC_TRUE
%assign numBuffer =3
%else
%assign isTransportdelay = TLC_FALSE
%assign numBuffer =2
%endif
%assign blockWidth = LibBlockOutputSignalWidth(0)
%if !isRSIM
real_T *pBuffer = &%<LibBlockRWork(TUbufferArea, "", "", 0)>;
%endif
int_T j;
%assign localRollThreshold = 2
%assign useConstBufSzVect = 0
%if WILL_ROLL(RollRegions, localRollThreshold)
%if SIZE(ParamSettings.BufferSize,1) > 1
%<LibGenConstVectWithInit(ParamSettings.BufferSize,tSS_INT32,"bufSz")>
%assign useConstBufSzVect = 1
%endif
%endif
%assign rollVars = ["/Tail","/Head",...
"/Last","/CircularBufSize",...
"/TUbufferPtrs", "/InitialOutput"]
%roll idx = RollRegions, lcv = localRollThreshold, block, "Roller", rollVars
%if lcv == ""
%assign paramSettingIdx = idx
%else
%if idx == 0
%assign paramSettingIdx = lcv
%else
%assign paramSettingIdx = "%<lcv> + %<idx>"
%endif
%endif
%if useConstBufSzVect
%assign bufSz = "bufSz[%<paramSettingIdx>]"
%else
%assign bufSz = (SIZE(ParamSettings.BufferSize,1) == 1? ...
ParamSettings.BufferSize[0]: ...
ParamSettings.BufferSize[paramSettingIdx])
%endif
%assign tail = LibBlockIWork(Tail,"",lcv,idx)
%assign head = LibBlockIWork(Head,"",lcv,idx)
%assign last = LibBlockIWork(Last,"",lcv,idx)
%assign bufferSiz = LibBlockIWork(CircularBufSize,"",lcv,idx)
%assign initOutput= LibBlockParameter(InitialOutput, "",lcv,idx)
%if isRSIM
%if lcv == ""
{
%endif
%assign utilName = TDelay_CreateBuf(block)
real_T *pBuffer = (real_T *)%<utilName>(%<numBuffer>, %<bufSz>, sizeof(real_T));
if (pBuffer == %<SLibGetNullDefinitionFromTfl()>) {
%<RTMSetErrStat("/"vtdelay memory allocation error/"")>;
return;
}
%endif
%<tail> = 0;
%<head> = 0;
%<last> = 0;
%<bufferSiz> = %<bufSz>;
for(j=0; j < %<bufSz>; j++){
pBuffer[j] = %<initOutput>;
pBuffer[%<bufSz> + j] = %<LibGetT()>;
}
%if lcv != ""
%assign pUbuf = LibBlockPWork(TUbufferPtrs, "", lcv, idx)
%assign pTbuf = LibBlockPWork(TUbufferPtrs, "", ...
"%<lcv>+%<blockWidth>", idx)
%if isTransportdelay
%assign pXbuf = LibBlockPWork(TUbufferPtrs, "", ...
"%<lcv>+%<2*blockWidth>", idx)
pBuffer[2*%<bufSz>] = 0.0;
%endif
%else
%assign pUbuf = LibBlockPWork(TUbufferPtrs, "", lcv, idx)
%assign pTbuf = LibBlockPWork(TUbufferPtrs, "", lcv, idx+blockWidth)
%if isTransportdelay
%assign pXbuf = LibBlockPWork(TUbufferPtrs, "", lcv, idx+2*blockWidth)
pBuffer[2*%<bufSz>] = 0.0;
%endif
%endif
%<pUbuf> = (void *) &pBuffer[0];
%<pTbuf> = (void *) &pBuffer[%<bufSz>];
%if isTransportdelay
%<pXbuf> = (void *) &pBuffer[2*%<bufSz>];
%endif
%if !isRSIM && ((lcv != "") || (lcv == "" && idx < blockWidth-1))
%if TYPE(bufSz) == "Number"
pBuffer += %;
%else
pBuffer += %<numBuffer>*%<bufSz>;
%endif
%endif
%if isRSIM && lcv == ""
}
%endif
%endroll
}
%endfunction
%function InitializeConditions(block, system) Output
%if (ParamSettings.Transportdelay == "yes" )
%assign ncStates = ContStates[0]
%assign rollRegions = [0:%]
%assign rollVars = ["Xc"]
%roll sigIdx = rollRegions, lcv = RollThreshold, block, "Roller", rollVars
%<LibBlockContinuousState("", lcv, sigIdx)> = 0.0;
%endroll
%else
%endif
%endfunction
%function FcnIsReal(strValue)
%assign temp = FEVAL("sscanf",strValue,"%f%1s")
%return SIZE(temp,0) == 1
%endfunction
%function Outputs(block, system) Output
{
%if (ParamSettings.Transportdelay == "yes" )
%assign isTransportdelay = TLC_TRUE
%else
%assign isTransportdelay = TLC_FALSE
%endif
%assign blockWidth = LibBlockOutputSignalWidth(0)
%assign inport0Width = LibBlockInputSignalWidth(0)
%assign useConstIsDiscVect = 0
%assign localRollThreshold = 2
%if WILL_ROLL(RollRegions, localRollThreshold)
%if SIZE(ParamSettings.DiscreteInput,1) > 1
%<LibGenConstVectWithInit(ParamSettings.DiscreteInput,...
tSS_BOOLEAN,"isDiscrete")>
%assign useConstIsDiscVect = 1
%endif
%endif
real_T **uBuffer = (real_T**)&%<LibBlockPWork(TUbufferPtrs,"","",0)>;
real_T **tBuffer = (real_T**)&%<LibBlockPWork(TUbufferPtrs,"","",...
blockWidth)>;
%if isTransportdelay
real_T **xBuffer = (real_T**)&%<LibBlockPWork(TUbufferPtrs,"","",...
2*blockWidth)>;
%endif
%if ::CompiledModel.StartTime != 0.0
%assign tStart = RTMGet("TStart")
%else
%assign tStart = 0.0
%endif
real_T simTime = %<LibGetT()>;
real_T appliedDelay;
%if isTransportdelay
%assign rollVars = ["Xc","y0",...
"/InitialOutput ","/Tail","/Head",...
"/Last","/CircularBufSize"]
%else
%if (ParamSettings.HandleZeroDelay == "yes")
%assign rollVars = ["u0", "u1","y0","/MaximumDelay",...
"/InitialOutput ", "/Tail","/Head",...
"/Last","/CircularBufSize"]
%else
%assign rollVars = ["u1","y0","/MaximumDelay",...
"/InitialOutput ", "/Tail","/Head",...
"/Last","/CircularBufSize"]
%endif
%endif
%roll idx = RollRegions, lcv = localRollThreshold, block, "Roller", rollVars
%assign tail = LibBlockIWork(Tail, "", lcv, idx)
%assign head = LibBlockIWork(Head, "", lcv, idx)
%assign last = LibBlockIWork(Last, "", lcv, idx)
%assign initOutput = LibBlockParameter(InitialOutput, "",lcv,idx)
%assign y = LibBlockOutputSignal(0, "", lcv, idx)
%if lcv == ""
%assign paramSettingIdx = idx
%else
%if idx == 0
%assign paramSettingIdx = lcv
%else
%assign paramSettingIdx = "%<lcv> + %<idx>"
%endif
%endif
%if useConstIsDiscVect
%assign isDiscrete = "isDiscrete[%<paramSettingIdx>]"
%else
%assign isDiscrete = (SIZE(ParamSettings.DiscreteInput,1) == 1? ...
ParamSettings.DiscreteInput[0]: ...
ParamSettings.DiscreteInput[paramSettingIdx])
%endif
%assign bufSz = LibBlockIWork(CircularBufSize, "", lcv, idx)
%if ( Accelerator || isRSim || ...
CodeFormat == "S-Function" || ...
SolverType == "VariableStep" || ...
IsModelReferenceForASimstructBasedTarget() )
%assign minorStepAndTAtLastMajorOutput = ...
"(boolean_T) " ...
"(%<RTMIs("MinorTimeStep")> && " ...
"(%<RTMGet("TimeOfLastOutput")> == %<LibGetT()>))"
%else
%assign minorStepAndTAtLastMajorOutput = 0
%endif
%if isTransportdelay
%assign utilName = VTDelay_FindtDInterpolate(block)
%assign x = LibBlockContinuousState("",lcv, idx)
/* For variable transport dealy, find the real applied dealy
* here and then output
*/
%<y>= %<utilName>(%<x>,*tBuffer,*uBuffer, *xBuffer,
%<bufSz>,%<head>,%<tail>, &%<last>, simTime, %<tStart>,%<isDiscrete>,
%<minorStepAndTAtLastMajorOutput>, %<initOutput>,
&appliedDelay);
%else
%assign maxDelay = LibBlockParameter(MaximumDelay, "", lcv, idx)
appliedDelay = %<LibBlockInputSignal(1, "", lcv, idx)>;
/* For variable time delay, output here */
if ( appliedDelay > %<maxDelay>) {
appliedDelay = %<maxDelay>;
}
if ( appliedDelay < 0.0) {
/* negative delay is not supported
* set delay to 0
*/
appliedDelay = 0.0;
}
%assign tMinusDelay = "simTime - appliedDelay"
%assign utilName = TDelay_Interpolate(block)
%if (ParamSettings.HandleZeroDelay == "yes")
if(appliedDelay == 0.0){
%assign u0 = LibBlockInputSignal(0, "", lcv, idx)
%<y> = %<u0>;
}
else{
%<y> = %<utilName>(
%<tMinusDelay>,
%<tStart>,
*tBuffer,
*uBuffer,
%<bufSz>,
&%<last>,
%<tail>,
%<head>,
%<initOutput>,
%<isDiscrete>,
%<minorStepAndTAtLastMajorOutput>);
}
%else
%<y> = %<utilName>(
%<tMinusDelay>,
%<tStart>,
*tBuffer,
*uBuffer,
%<bufSz>,
&%<last>,
%<tail>,
%<head>,
%<initOutput>,
%<isDiscrete>,
%<minorStepAndTAtLastMajorOutput>);
%endif
%endif
%if (lcv != "") || (lcv == "" && idx < blockWidth-1)
tBuffer++; uBuffer++;
%if isTransportdelay
xBuffer++;
%endif
%endif
%endroll
}
%endfunction
%function Update(block, system) Output
{
%if (ParamSettings.Transportdelay == "yes" )
%assign isTransportdelay = TLC_TRUE
%else
%assign isTransportdelay = TLC_FALSE
%endif
%assign blockWidth = LibBlockOutputSignalWidth(0)
%assign inport0Width = LibBlockInputSignalWidth(0)
real_T **uBuffer = (real_T**)&%<LibBlockPWork(TUbufferPtrs,"","",0)>;
real_T **tBuffer = (real_T**)&%<LibBlockPWork(TUbufferPtrs,"","",...
blockWidth)>;
%if isTransportdelay
real_T **xBuffer = (real_T**)&%<LibBlockPWork(TUbufferPtrs,"","",...
2*blockWidth)>;
%elseif isRSim || Accelerator
real_T **xBuffer = %<SLibGetNullDefinitionFromTfl()>;
%endif
real_T simTime = %<LibGetT()>;
%if (ParamSettings.FixedBuffer == "yes" )
%assign isFixedbuf = TLC_TRUE
boolean_T bufferisfull = %;
%else
%assign isFixedbuf = TLC_FALSE
%endif
%<LibUpdateBlockCStateAbsoluteTolerance(block, system)>
%assign delayPrm = "MaximumDelay"
%assign rollVars = ["u0", "u1", "/Tail","/Head", ...
"/CircularBufSize", "/%<delayPrm>"]
%if isTransportdelay
%assign rollVars = ["Xc","u0","u1", "/Tail","/Head", ...
"/CircularBufSize"]
%endif
%if Accelerator || isRSim
%assign rollVars = ["u0", "u1", "/Tail","/Head", ...
"/Last", "/CircularBufSize", "/%<delayPrm>"]
%assign maxNewBufSz = LibBlockIWork(MaxNewBufSize, "", "", 0)
%if isTransportdelay
%assign rollVars = ["Xc","u0", "u1", "/Tail","/Head", ...
"/Last", "/CircularBufSize", "/%<delayPrm>"]
%endif
%endif
%roll idx = RollRegions, lcv = RollThreshold, block, "Roller", rollVars
%assign tail = LibBlockIWork(Tail, "", lcv, idx)
%assign head = LibBlockIWork(Head, "", lcv, idx)
%assign bufSz = LibBlockIWork(CircularBufSize, "", lcv, idx)
%<head> = ((%<head> < (%<bufSz>-1)) ? (%<head>+1) : 0);
if (%<head> == %<tail>) {
%if isFixedbuf
bufferisfull = %;
%endif
%if Accelerator || isRSim
%assign last = LibBlockIWork(Last, "", lcv, idx)
%assign tDelay = LibBlockParameter(%<delayPrm>, "", lcv, idx)
%assign tMinusDelay = "simTime - %<tDelay>"
%assign utilName = TDelay_UpdateTailOrGrowBuf(block)
if (!%<utilName>( &%<bufSz>, ...
&%<tail>, &%<head>, &%<last>, %<tMinusDelay>, ...
tBuffer, uBuffer, xBuffer,(boolean_T)%<isFixedbuf>, ...
(boolean_T)%<isTransportdelay>,
&%<maxNewBufSz>) ) {
%<RTMSetErrStat("/"vtdelay memory allocation error/"")>;
return;
}
%else
%<tail> = ((%<tail> < (%<bufSz>-1)) ? (%<tail>+1) : 0);
%endif
}
%if (lcv != "") || (lcv == "" && idx < blockWidth-1)
%assign pp = "++"
%else
%assign pp = ""
%endif
(*tBuffer%<pp>)[%<head>] = simTime;
%if (inport0Width == 1)
(*uBuffer%<pp>)[%<head>] = %<LibBlockInputSignal(0, "", "", 0)>;
%else
(*uBuffer%<pp>)[%<head>] = %<LibBlockInputSignal(0, "", lcv, idx)>;
%endif
%if isTransportdelay
%assign x = LibBlockContinuousState("",lcv, idx)
(*xBuffer%<pp>)[%<head>] = %<x>;
%endif
%endroll
/* when use fixed buffer, reset solver at when buffer is updated
* to avoid output consistency fail.
*/
%if isFixedbuf
if (bufferisfull){
%<RTMSetBlockStateForSolverChangedAtMajorStep()>;
%<RTMSetContTimeOutputInconsistentWithStateAtMajorStep()>;
}
%endif
}
%endfunction
%function Derivatives(block, system) Output
{
%if (ParamSettings.Transportdelay == "yes" )
real_T instantDelay;
%assign rollVars = ["u1", "xdot", "/MaximumDelay"]
%roll idx = RollRegions, lcv = 2, block, "Roller", rollVars
instantDelay = %<LibBlockInputSignal(1, "", lcv, idx)>;
%assign maxDelay = LibBlockParameter(MaximumDelay, "", lcv, idx)
if ( instantDelay > %<maxDelay>) {
instantDelay = %<maxDelay>;
}
if (instantDelay < 0.0) {
%<LibBlockContinuousStateDerivative("",lcv,idx)> = 0;
}else{
%<LibBlockContinuousStateDerivative("",lcv,idx)> = 1.0/instantDelay;
}
%endroll
%else
%endif
}
%endfunction
%function ForcingFunction(block, system) Output
%if ::CompiledModel.ModelIsLinearlyImplicit == "yes"
%<Derivatives(block,system)>
%endif
%endfunction
%function Terminate(block, system) Output
%<TDelay_Terminate(block, system)>
%endfunction