%%
%%
%%
%%Abstract:
%%TLCfileforgeneratingrt_ZCFcnfunctionviaTargetFunction
%%Library(TFL).
%%
%%Copyright2003-2018TheMathWorks,Inc.
 
%implements "genrtzcfcn" "C"
 
%%Function:rt_ZCFcn=========================================================
%%Abstract:
%%GENERATEentrypointforTargetFunctionLibraryTLCcallbacks.Creates
%%headerandsourcefilecontentsforrt_ZCFcnandrt_I32ZCFcnfunctions.
%%
%function rt_ZCFcn(fctInfo,fileH,fileC) void
 
  %assign zcfcnStr = "rt_ZCFcn"
 
  %% Create header file contents
  %openfile buf
  /*
  * %<fctInfo.FileName>.h
  *
  %<SLibCommonUtilHeaderInfo()>/
  */
  %closefile buf
  %<SLibCacheUtilCodeToFile("util_hdr_banner", fileH, buf)>
 
  %openfile buf
  #include "%<SLibCoderTypesFilename()>"
  %closefile buf
  %<SLibCacheUtilCodeToFile("util_hdr_incl", fileH, buf)>
   
  %openfile buf
  #include "solver_zc.h"
     
  %% In ERT mode include zero crossing types header; if not ERT, these
  %% definitions are provided by the main types definitions file.
  %if SLibIsERTTarget()
    #include "%<SLibCoderZerocrossingTypesFilename()>"
  %endif
   
  #ifndef slZcHadEvent
  #define slZcHadEvent(ev, zcsDir) (((ev) & (zcsDir)) != 0x00 )
  #endif
  %closefile buf
  %<SLibCacheMacroToUtilityFile("slZcHadEvent", buf, "util_hdr_defines", fileH)>
  %openfile buf
    #ifndef slZcUnAliasEvents
    #define slZcUnAliasEvents(evL, evR) /
            ((((slZcHadEvent((evL), (SL_ZCS_EVENT_N2Z)) && /
            slZcHadEvent((evR), (SL_ZCS_EVENT_Z2P))) || /
            (slZcHadEvent((evL), (SL_ZCS_EVENT_P2Z)) && /
            slZcHadEvent((evR), (SL_ZCS_EVENT_Z2N)))) ? /
            (SL_ZCS_EVENT_NUL) : (evR)))
    #endif
  %closefile buf
  %<SLibCacheMacroToUtilityFile("slZcUnAliasEvents", buf, "util_hdr_defines", fileH)>
   
  %assign msFcn = SLibGetMemSecCategoryForUtilityFcn()
  %assign fcnName = zcfcnStr
  %openfile buf
  %<FcnGenOpenExternCForCPP()>
  %<SLibGetFcnMemSecPragmaOnDecl(fcnName, msFcn, "Pre")>/
  %<LibStaticOrExternInFcnDecls()>ZCEventType %<zcfcnStr>(ZCDirection zcDir, /
                              ZCSigState *prevZc, /
                              real_T currValue);
  %<SLibGetFcnMemSecPragmaOnDecl(fcnName, msFcn, "Post")>/
  %<FcnGenCloseExternCForCPP()>
  %closefile buf
  %<SLibCacheUtilCodeToFile("util_hdr_decl", fileH, buf)>
   
  %% Create source file contents
  %openfile buf
  /*
  * %<fctInfo.FileName>.%<LangFileExt>
  *
  %<SLibCommonUtilHeaderInfo()>/
  */
  %closefile buf
  %<SLibCacheUtilCodeToFile("util_src_banner", fileC, buf)>
   
  %openfile buf
  #include "rt_zcfcn.h"
 
  %closefile buf
  %<SLibCacheUtilCodeToFile("util_src_incl", fileC, buf)>
 
  %openfile buf
  %if GenCPP
  extern "C" {
  %endif
  %assign fcnReturns = "ZCEventType"
  %assign fcnParams = "ZCDirection zcDir, ZCSigState* prevZc, real_T currValue"
  %assign fcnAbstract = "Detect zero crossings events."
  %assign functionSpecifier = LibStaticInFcnDecls()
  %createrecord fcnRec {Name fcnName; Returns fcnReturns; Params fcnParams; Abstract fcnAbstract; ...
    Category "utility"; GeneratedBy "genrtzcfcn.tlc"}
  %<SLibDumpFunctionBanner(fcnRec)>
  %undef fcnRec
  %<SLibGetFcnMemSecPragma(fcnName, msFcn, "Pre")>/
   %<functionSpecifier> %<fcnReturns> %<fcnName>(%<fcnParams>)
   {
     slZcEventType zcsDir;
     slZcEventType tempEv;
     ZCEventType zcEvent = NO_ZCEVENT; /* assume */
     
     /* zcEvent matrix */
     static const slZcEventType eventMatrix[4][4] = {
        /* ZER POS NEG UNK */
        {SL_ZCS_EVENT_NUL,SL_ZCS_EVENT_Z2P,SL_ZCS_EVENT_Z2N,SL_ZCS_EVENT_NUL},/* ZER */
        {SL_ZCS_EVENT_P2Z,SL_ZCS_EVENT_NUL,SL_ZCS_EVENT_P2N,SL_ZCS_EVENT_NUL},/* POS */
        {SL_ZCS_EVENT_N2Z,SL_ZCS_EVENT_N2P,SL_ZCS_EVENT_NUL,SL_ZCS_EVENT_NUL},/* NEG */
        {SL_ZCS_EVENT_NUL,SL_ZCS_EVENT_NUL,SL_ZCS_EVENT_NUL,SL_ZCS_EVENT_NUL} /* UNK */
     };
     
     /* get prevZcEvent and prevZcSign from prevZc */
     slZcEventType prevEv = (slZcEventType)(((uint8_T)(*prevZc)) >> 2);
     slZcSignalSignType prevSign = (slZcSignalSignType)(((uint8_T)(*prevZc)) & (uint8_T)0x03);
     
     /* get current zcSignal sign from current zcSignal value */
     slZcSignalSignType currSign = (slZcSignalSignType)((currValue) > 0.0 ? SL_ZCS_SIGN_POS :
          ((currValue) < 0.0 ? SL_ZCS_SIGN_NEG : SL_ZCS_SIGN_ZERO));
     
     /* get current zcEvent based on prev and current zcSignal value */
     slZcEventType currEv = eventMatrix[prevSign][currSign];
    
     /* get slZcEventType from ZCDirection */
     switch (zcDir) {
       case ANY_ZERO_CROSSING:
         zcsDir = SL_ZCS_EVENT_ALL;
         break;
       case FALLING_ZERO_CROSSING:
         zcsDir = SL_ZCS_EVENT_ALL_DN;
         break;
       case RISING_ZERO_CROSSING:
         zcsDir = SL_ZCS_EVENT_ALL_UP;
         break;
       default:
         zcsDir = SL_ZCS_EVENT_NUL;
         break;
     }
     
     /*had event, check if double zc happend remove double detection. */
     if ( slZcHadEvent(currEv, zcsDir)) {
       currEv = (slZcEventType)(slZcUnAliasEvents(prevEv, currEv));
     } else{
       currEv = SL_ZCS_EVENT_NUL;
     }
     
     /* Update prevZc */
     tempEv = (slZcEventType)(currEv << 2); /* shift left by 2 bits */
     *prevZc = (ZCSigState)((currSign) | (tempEv));
     
     if ((currEv & SL_ZCS_EVENT_ALL_DN) != 0) {
       zcEvent = FALLING_ZCEVENT;
     }else if ((currEv & SL_ZCS_EVENT_ALL_UP) != 0){
       zcEvent = RISING_ZCEVENT;
     }else{
       zcEvent = NO_ZCEVENT;
     }
 
     return zcEvent;
   } /* %<zcfcnStr> */
  %<SLibGetFcnMemSecPragma(fcnName, msFcn, "Post")>/
   
  %if GenCPP
  }
  %endif
   
  %closefile buf
  %<SLibCacheUtilCodeToFile("util_src_fcn_defn", fileC, buf)>
%endfunction