%%
%%
%%
%%Abstract:
%%TLCfileforgeneratingrt_I32ZCFcnfunctionviaTargetFunction
%%Library(TFL).
%%
%%Copyright2003-2018TheMathWorks,Inc.
 
%implements "genrti32zcfcn" "C"
 
%%Function:rt_I32ZCFcn======================================================
%%Abstract:
%%GENERATEentrypointforTargetFunctionLibraryTLCcallbacks.Creates
%%headerandsourcefilecontentsforrt_I32ZCFcn.
%%
%function rt_I32ZCFcn(fctInfo,fileH,fileC) void
 
  %assign i32zcfcnStr = "rt_I32ZCFcn"
 
  %% 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 = "%<i32zcfcnStr>"
  %openfile buf
  %<FcnGenOpenExternCForCPP()>
  %<SLibGetFcnMemSecPragmaOnDecl(fcnName, msFcn, "Pre")>/
  %<LibStaticOrExternInFcnDecls()>ZCEventType %<i32zcfcnStr>(ZCDirection zcDir, /
                                    ZCSigState *prevZc, /
                                    int32_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_i32zcfcn.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, int32_T currValue"
  %assign fcnAbstract = "Detect zero crossings events."
  %assign functionSpecifier = LibStaticInFcnDecls()
  %createrecord fcnRec {Name fcnName; Returns fcnReturns; Params fcnParams; ...
    Abstract fcnAbstract; Category "utility"; GeneratedBy "genrti32zcfcn.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 ? SL_ZCS_SIGN_POS :
          ((currValue) < 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;
    } /* end %<i32zcfcnStr> */
  %<SLibGetFcnMemSecPragma(fcnName, msFcn, "Post")>/
   
  %if GenCPP
  }
  %endif
   
  %closefile buf
  %<SLibCacheUtilCodeToFile("util_src_fcn_defn", fileC, buf)>
%endfunction