%%============================================================================
%%File:ertmdlrefabstime.tlc
%%
%%Abstract:
%%Eachtaskhasitsowntimer.Onlytaskneedabsolutetimewill
%%generatetimerandupdatetimeratitssamplerate.
%%Generatepureintegertimerfordiscretetimetask.
%%(1)Ifanyblockneedabsolutetime,theblockmarksNeedAbsoluteTimeof
%%itstidtobetrue.ThisisdumpedfromSImulinkto.rtwfile.
%%(2)Ifdataloggingison,NeedAsoluteTimefortid0isalwaystrue.
%%(3)Ifthereexistblockthataccessabsolutetimebutdon'tclaim
%%NeedAbsoluteTime,obsoletefloatingabsolutetimerisgeneratedfor
%%backwardcompatibility.
%%(4)SeeSLibSetupAbsoluteTimeformoreinfo.
%%Issues:
%%(1)IfablockusesLibGetT,inamulti-rate,multi-taskingmodel,theblock
%%mayusethetimeofothertasks.
%%(2)Renamethisfunction:SLibNeedObsAbsoluteTime.Thisfunctionhasstate,
%%anditonlyshouldbecalledduringcodeblock'scodegeneration.
%%TimingcodelikeertshoulduseSLibIsObsAbsoluteTimeRequired
%%(3)Absolutetimefortid0andtid1,iftid01isequal,arethesame.
%%Whydoweneedboth?
%%
%%
%%============================================================================
%selectfile NULL_FILE
 
%if EXISTS("_ERT_MODELREF_ABS_TIME_") == 0
%assign _ERT_MODELREF_ABS_TIME_ = 1
 
%function SLibGenAbsTimeComment(tid)
  %assign tsRec = SampleTime[tid]
  %openfile retBuf
  %if tsRec.NeedFloatTime == "yes"
    /* The "clockTick%<tid>" counts the number of times the code of this task has
    * been executed. The absolute time is the multiplication of "clockTick%<tid>"
    * and "Timing.stepSize%<tid>". Size of "clockTick%<tid>" ensures timer will not
    * overflow during the application lifespan selected.
    %if SLibClockTickIsUnit32Pair(tid)
      * Timer of this task consists of two 32 bit unsigned integers.
      * The two integers represent the low bits Timing.clockTick%<tid> and the high bits
      * Timing.clockTickH%<tid>. When the low bit overflows to 0, the high bits increment.
    %endif
    */
  %else
    /* The "clockTick%<tid>" counts the number of times the code of this task has
    * been executed. The resolution of this integer timer is %<tsRec.ClockTickStepSize>, which is the step size
    * of the task. Size of "clockTick%<tid>" ensures timer will not overflow during the
    * application lifespan selected.
    %if SLibClockTickIsUnit32Pair(tid)
      * Timer of this task consists of two 32 bit unsigned integers.
      * The two integers represent the low bits Timing.clockTick%<tid> and the high bits
      * Timing.clockTickH%<tid>. When the low bit overflows to 0, the high bits increment.
    %endif
    */
  %endif
  %closefile retBuf
   
  %return retBuf
%endfunction
 
%%Function:RTMUpdateAbsoluteTimeForTID=================
%%
%%
%function RTMUpdateAbsoluteTimeForTID(tid) void
  %openfile tmpBuf
  %%
  %<SLibGenAbsTimeComment(tid)>
  %if SampleTime[tid].NeedFloatTime == "yes"
    %<RTMUpdateRealAbsoluteTimeForTID(tid)>
  %else
    %<RTMUpdateIntegerAbsoluteTimeForTID(tid)>
  %endif
  %closefile tmpBuf
   
  %return tmpBuf
   
%endfunction
 
%%FunctionFcnUpdateAbsoluteTimeNonRateGrouping=======================
%%Abstract:
%%Generateabsolutetimeforalltidsifitisrequired.
%function FcnUpdateAbsoluteTimeNonRateGrouping(ssIdx) void
  %% RTMArgDef is accessed
  %assign absTimeDumped = TLC_FALSE
   
  %openfile tmpBuf
  %% enhanced absolute time
  %if SLibNeedAbsoluteTimeForTID(0)
    %% If tid 0 is continuous and is model reference Simstruc based,
    %% all continuous time related information is accessed from simstruct.
    %if !LibIsContinuous(0) || !IsModelReferenceForASimstructBasedTarget()
      %% We are not rate grouping, so we need to guard for TID 0.
      /* Update absolute time for base rate */
      %if !SLibSingleTasking()
    %assign guard = LibIsSampleHit(0)
    %if guard != "1"
      if (%<guard>) {
    %endif
      %endif
      %<RTMUpdateAbsoluteTimeForTID(0)>
      %if !SLibSingleTasking() && guard != "1"
        }
      %endif
      %assign absTimeDumped = TLC_TRUE
    %endif
  %endif
  %foreach tidIdx = NumRuntimeExportedRates -1
    %assign subRateIdx = tidIdx + 1
    %if SLibNeedAbsoluteTimeForTID(subRateIdx)
       
      %if !SLibSingleTasking()
    %assign tidGuard = LibIsSampleHit(subRateIdx)
      %else
        %if SLibControllableRateTID(subRateIdx)
          %assign baseTID = ::CompiledModel.SampleTime[subRateIdx].CtrlRateBaseTID
          %assign tidGuard = ((baseTID == 1 && FixedStepOpts.TID01EQ) || baseTID == 0) ? ...
            "1" : LibIsSpecialSampleHit(baseTID, 0)
        %else
          %assign tidGuard = (subRateIdx == 1 && FixedStepOpts.TID01EQ) ? ...
            "1" : LibIsSpecialSampleHit(subRateIdx, 0)
        %endif
      %endif
      %if tidGuard == "1"
    {
      %else
    if (%<tidGuard>) {
      %endif
      %assign period = ::CompiledModel.SampleTime[subRateIdx].PeriodAndOffset[0]
      %assign offset = ::CompiledModel.SampleTime[subRateIdx].PeriodAndOffset[1]
           /* Update absolute timer for sample time: [%<period>s, %<offset>s] */
       %<RTMUpdateAbsoluteTimeForTID(subRateIdx)>
     }
      %assign absTimeDumped = TLC_TRUE
    %endif
  %endforeach
  %closefile tmpBuf
   
  %if absTimeDumped
    %assign arg = ::CompiledModel.System[ssIdx].Interface.RTMArgDef
    %<SLibAccessArgHelper(arg,"","")>
  %endif
 
  %return tmpBuf
%endfunction %%FcnUpdateAbsoluteTimeNonRateGrouping
 
 
%%FunctionFcnUpdateAbsoluteTimeRateGrouping=======================
%%Abstract:
%%Generatefloatpointabsolutetimeifthetid
%%NeedFloatTime.SeeSLibSetupAbsoluteTimetofindout
%%howtheNeedFloatTimelogiciscalculated.
%function FcnUpdateAbsoluteTimeRateGrouping(ssIdx, subRateIdx) void
  %assign tmpBuf = ""
 
  %if SLibNeedAbsoluteTimeForTID(subRateIdx)
    %openfile tmpBuf
    %assert(SampleTime[subRateIdx].NeedAbsoluteTime == "yes")
    %% If tid 0 is continuous and is model reference Simstruc based,
    %% all continuous time related information is accessed from simstruct.
    %if !LibIsContinuous(subRateIdx) || ...
      !IsModelReferenceForASimstructBasedTarget()
      /* Update absolute time */
      %<RTMUpdateAbsoluteTimeForTID(subRateIdx)>
    %endif
    %closefile tmpBuf
    %assign arg = ::CompiledModel.System[ssIdx].Interface.RTMArgDef
    %<SLibAddTIDtoAccessTIDList(arg, ::BlockFcn, "",subRateIdx)>
  %endif
   
  %return tmpBuf
%endfunction
 
%%Function:FcnUpdateAsyncTimeAtMinorMajorTimeStep======================
%%
%function FcnUpdateAsyncTimeAtMinorMajorTimeStep()
  %assert(!IsModelReferenceTarget())
  %openfile tmpBuf
   
  %foreach idx = LibGetNumAsyncTasks()
    %assign tid = idx + NumRuntimeExportedRates
    %if !RTMAbsTimeNeedTransProtection(tid)
      %continue
    %endif
    %assert !SLibConcurrentTasks()
    %if RTMContTDbBufIsReqFcn(%<tid>)
       /* Base rate updates double buffers of absolute time at
       minor and major time step for asynchronous task %<tid>.
       Double buffers are used to ensure data integrity when
       asynchronous task reads absolute time.
       */
      switch(%<SLibGetDbBufReadBuf(tid)>) {
    case 0: %<SLibGetDbBufWriteBuf(tid)> =1; break;
    case 1: %<SLibGetDbBufWriteBuf(tid)> =0; break;
    default: %<SLibGetDbBufWriteBuf(tid)> = ...
      !%<SLibGetDbBufLastBufWr(tid)>; break;
      }
      %<SLibGetDbBufContTForTID(tid)>[%<SLibGetDbBufWriteBuf(tid)>] = ...
    %<LibGetT()>;
      %<SLibGetDbBufLastBufWr(tid)> = %<SLibGetDbBufWriteBuf(tid)>;
      %<SLibGetDbBufWriteBuf(tid)> = 0xFF;
    %elseif RTMContTH2LIsReqFcn(tid)
      /* Base rate updates double-buffer of absolute time
      at minor and major time step for asynchronous task %<tid>.
      Double buffers are used to ensure data integrity
      when asynchronous task reads absolute time.
      -- rtmH2LBufBeingRead is the index of the buffer being read
         by the asynchronous task %<tid>
      -- rtmH2LLastBufWr is the index of the buffer that is
      written last.
      */
      if (%<SLibGetH2LBufBeingRead(tid)> != 0) {
    %<SLibGetH2LDbBufContTForTID(tid)>[0] = %<LibGetT()>;
    %<SLibGetH2LLastBufWr(tid)> = 0;
      } else {
    %<SLibGetH2LDbBufContTForTID(tid)>[1] = %<LibGetT()>;
    %<SLibGetH2LLastBufWr(tid)> = 1;
      }
    %endif
  %endforeach
 
  %if RTMContTL2HIsReqFcn()
     {
       /* Base rate updates double buffers of absolute time at
       minor and major time step for asynchronous task %<tid>.
       Double buffers are used to ensure data integrity when
       asynchronous task reads absolute time.
       -- rtmL2HLastBufWr is the index of the buffer that is
       written last.
       */
       boolean_T bufIdx = !%<SLibGetL2HLastBufWr()>;
 
       %<SLibGetL2HDbBufContT()>[bufIdx] = %<LibGetT()>;
       %<SLibGetL2HLastBufWr()> = bufIdx;
     }
   %endif
     
   %closefile tmpBuf
   %return tmpBuf
%endfunction %% FcnUpdateAsyncTimeAtMinorMajorTimeStep
 
%%Function:FcnUpdateAsyncTaskTimers===========================
%%Abstract:
%%Forasynchronoustasksthatdon'tmanageownabsolutetime,
%%tasktimeisobtainedfromabsolutetimeforbaserate.
%%Toinsuredataintegrity,codeforobtainingasynctasktime
%%hastwoparts:onepartrunsatbaserate,theotherpartruns
%%whenasynchronoustaskruns.
%%Thisfunctiongeneratecodethatrunsatthebaserate.
%%FcnAsyncTaskUpdatesTimersFromBaseRategeneratescodethat
%%runswithasynchronoustasks.
%%
%%Weonlyneedobtaintabsolutetimefrombaserateforasynctaskif
%%thetaskneedabsolutetimeandasynctaskdoesNOTmanageown
%%absolutetimer.
%%Therearethreecases:
%%1:Asynchronoustaskpriorityisunknown.Doublebuffersareused
%%toinsuredataintegrity.
%%Atbaseratetask:
%%switch(ReadBuf(){
%%case0:WriteBuf=1;break;
%%case1:WriteBuf=0;break;
%%default:WriteBuf=LastBufWr;break;
%%}
%%DbBuf_of_ClockTickForAsyncTID[WriteBuf]=currenttime
%%LastBufWr=WriteBuf;
%%WriteBuf=None;
%%Atasyncratetask
%%switch(WriteBuf(){
%%case0:ReadBuf=1;break;
%%case1:ReadBuf=0;break;
%%default:ReadBuf=!LastBufWr;break;
%%}
%%ClockTickForAsyncTID=DbBuf_of_ClockTickForAsyncTID[ReadBuf]
%%ReadBuf=None;
%%
%%2:Asynchronoustaskpriorityishigherthanbaserate.Doublebuffers
%%areusedtoensuredataintegrity.
%%Atbaserate,clockTick0iswrittenintoinactivebuffer.
%%afterwrittingprocesscomplete,updatetheflag
%%L2HLastBufWr--idxofbufferlastwritten.
%%Atsynctask,asynctaskreadsclockTick%<tid>from
%%thebufferthatislastwritten
%%
%%3:Asynchronoustaskpriorityislowerthanbaserate.Doublebuffers
%%areusedtoensuredataintegrity.Twoflags:
%%H2LLastBufWr--idxofbufferlastwritten
%%H2LBufBeingRead--numberofasychronoustasksthatarereaddingbuffer0
%%Atbaserate,ifnotaskisreadingbuffer0,clockTick0iswritteninto
%%buffer0,otherwisewritetobuffer1.Thenupdatetheflag
%%H2LLastBufWr
%%Atasynctask,asynctaskreadsclockTick%<tid>from
%%thebufferthatislastwritten.Ifthelastbufferwritten
%%isbuffer0,increaseH2LBufBeingReadby1beforereading,
%%decreaseby1whenreadingcomplete.
%%
%function FcnUpdateAsyncTaskTimers() void
  %assert(!IsModelReferenceTarget())
  %openfile tmpBuf
   
  %foreach tid = NumSampleTimes
    %if !RTMAbsTimeNeedTransProtection(tid)
      %continue
    %endif
    %if SLibConcurrentTasks()
      %<SLibCGIRMutexOp(1,SLibGetTimerSemID(tid))>
      %<LibGetClockTickBufForTID">SLibGetClockTickBufForTID(tid)> = %<LibGetClockTick(0)>;
      %if SLibClockTickIsUnit32Pair(tid)
        %<SLibGetClockTickHBufForTID(tid)> = %<LibGetClockTickHigh(0)>;
      %endif
      %<SLibCGIRMutexOp(2,SLibGetTimerSemID(tid))>
      %continue
    %endif
    %if RTMClockTick0DbBufIsReqFcn(tid)
      switch(%<SLibGetDbBufReadBuf(tid)>) {
    case 0: %<SLibGetDbBufWriteBuf(tid)> =1; break;
    case 1: %<SLibGetDbBufWriteBuf(tid)> =0; break;
    default: %<SLibGetDbBufWriteBuf(tid)> = ...
      !%<SLibGetDbBufLastBufWr(tid)>; break;
      }
 
      %<SLibGetDbBufClockTickForTID(tid)>[%<SLibGetDbBufWriteBuf(tid)>] = ...
    %<LibGetClockTick(0)>;
      %if SLibClockTickIsUnit32Pair(tid)
    %<SLibGetDbBufClockTickHForTID(tid)>[%<SLibGetDbBufWriteBuf(tid)>] = ...
      %<LibGetClockTickHigh(0)>;
      %endif
      %<SLibGetDbBufLastBufWr(tid)> = %<SLibGetDbBufWriteBuf(tid)>;
      %<SLibGetDbBufWriteBuf(tid)> = 0xFF;
    %elseif RTMClockTick0H2LIsReqFcn(tid)
      /* Base rate updates double buffers of absolute time for
      asynchronous task %<tid>. Double buffers are used to
      ensure data integrity when asynchronous task reads
      absolute time.
      -- rtmH2LBufBeingRead is the index of the buffer being
         read by the asynchronous task %<tid>
      -- rtmH2LLastBufWr is the index of the buffer that is
         written last.
      */
      if (%<SLibGetH2LBufBeingRead(tid)> != 0) {
    %<SLibGetH2LDbBufClockTickForTID(tid)>[0] = %<LibGetClockTick(0)>;
    %if LongClockTickForTIDIsReqFcn(0)
      %<SLibGetH2LDbBufClockTickHForTID(tid)>[0] = %<LibGetClockTickHigh(0)>;
    %endif
    %<SLibGetH2LLastBufWr(tid)> = 0;
      } else {
    %<SLibGetH2LDbBufClockTickForTID(tid)>[1] = %<LibGetClockTick(0)>;
    %if LongClockTickForTIDIsReqFcn(0)
      %<SLibGetH2LDbBufClockTickHForTID(tid)>[1] = %<LibGetClockTickHigh(0)>;
    %endif
    %<SLibGetH2LLastBufWr(tid)> = 1;
      }
    %endif
  %endforeach
 
  %if RTMClockTick0L2HIsReqFcn()
     {
       /* Base rate updates double buffers of absolute time for
       asynchronous task. Double buffers are used to ensure
       data integrity when asynchronous task reads absolute
       time.
       -- rtmL2HLastBufWr is the buffer index that is written last.
       */
       boolean_T bufIdx = !%<SLibGetL2HLastBufWr()>;
 
       %<SLibGetL2HDbBufClockTick()>[bufIdx] = %<LibGetClockTick(0)>;
       %if LongClockTickForTIDIsReqFcn(0)
     %<SLibGetL2HDbBufClockTickH()>[bufIdx] = %<LibGetClockTickHigh(0)>;
       %endif
       %<SLibGetL2HLastBufWr()> = bufIdx;
     }
   %endif
     
   %closefile tmpBuf
   %return tmpBuf
%endfunction %% end FcnUpdateAsyncTaskTimers
       
 
%%Function:SLibErtGenUpdateAbsoluteTimeCode==========================================
%%Abstract:
%%(1)Forrategroupingcode,iftidneedsabsolutetime,
%%generatespecificupdatetimebufferforthetid.
%%*ThisbufferwillbedumpedwiththeUPDATEoutputUpdatefunctionof
%%eachtid.
%%(2)Fornon-rategroupingcode,andifthemodelneedsabsolutetime,
%%generateupdatetimebuffer.Thisbufferupdatestimerforalltids
%%thatneedabsolutetime.CodeisguardedbyIsSampleHit.
%%*ThisbufferwillbedumpedwiththeUPDATEoroutputupdatefunction.
%%
%%(3)Ifobsoletetimerisrequired,generateit.
%%*ThisbufferisdumpedwithOUTPUToroutputUpdatefunctionfortid0
%%(rategrouping)orwithOUTPUToroutput/updatefunction
%%(non-rategrouping).Thisifforbackwardcompatibility.
%%
%function SLibErtGenUpdateAbsoluteTimeCode(ssIdx, buffsRec, isPeriodicRateGrouping) void
  %assign ::initBlockFcn = ::BlockFcn
  %assign ::BlockFcn = "Update"
   
  %if isPeriodicRateGrouping
    %foreach subRateIdx = NumRuntimeExportedRates
      %openfile tmpBuf
      %assign System[ssIdx].CurrentTID = subRateIdx
      %<FcnUpdateAbsoluteTimeRateGrouping(ssIdx, subRateIdx)>
      %if subRateIdx == 0 && !IsModelReferenceTarget()
    %<FcnUpdateAsyncTaskTimers()>
      %endif
      %closefile tmpBuf
      %addtorecord buffsRec UpdateAbsoluteTimeBuffer%<subRateIdx> tmpBuf
    %endforeach
    %assign System[ssIdx].CurrentTID = -1
     
    %if FixedStepOpts.TID01EQ
      %assign tmpBuf0 = buffsRec.UpdateAbsoluteTimeBuffer0
      %assign tmpBuf1 = buffsRec.UpdateAbsoluteTimeBuffer1
       
      %assign buffsRec.UpdateAbsoluteTimeBuffer0 = tmpBuf0 + tmpBuf1
      %assign buffsRec.UpdateAbsoluteTimeBuffer1 = ""
    %endif
  %else
    %openfile updateTimeBuffer
    %<FcnUpdateAbsoluteTimeNonRateGrouping(ssIdx)>
    %if !IsModelReferenceTarget()
      %<FcnUpdateAsyncTaskTimers()>
    %endif
    %closefile updateTimeBuffer
    %addtorecord buffsRec UpdateAbsoluteTimeBuffer updateTimeBuffer
  %endif
   
  %assign ::BlockFcn = initBlockFcn
%endfunction %% SLibErtGenUpdateAbsoluteTimeCode
 
 
%endif %% _ERT_MODELREF_ABS_TIME_
 
%%[EOF]ertmdlrefabstime.tlc