Function block FB_GET_MIN_MAX

Declaration part:

FUNCTION_BLOCK FB_GET_MIN_MAX
VAR CONSTANT
   CMAXinit       :REAL := -3.402823E+38;
   CMINinit       :REAL := 3.402823E+38;
END_VAR
VAR_INPUT
   bInit         :BOOL := TRUE;
   nInputValue   :REAL;
   nMinFreqInput :REAL;
END_VAR
VAR_OUTPUT
   bRESULT       :BOOL;
   nMaxVal       :REAL;
   nMinVal       :REAL;
END_VAR
VAR
   CMMcnt        :UINT;
   nMaxValCnt    :UINT;
   nMinValCnt    :UINT;
   bValidMinVal  :BOOL;
   bValidMaxVal  :BOOL;
   fbGetCurTaskIdx : GETCURTASKINDEX;
END_VAR

Execution part:

IF bInit THEN
   // Counter initialization:
   // [counter value] > [1/(<input frequency> * TaskCycleTime)]
   fbGetCurTaskIdx();
   CMMcnt := REAL_TO_UINT(
      1.1E7/(nMinFreqInput*UDINT_TO_REAL(
      _TaskInfo[fbGetCurTaskIdx.index].CycleTime)));
   // At least an entire period have to be sampled for min/max determination
   // Initialization, go on:
   nMaxValCnt :=CMMcnt;
   nMinValCnt :=CMMcnt;
   nMaxVal :=CMAXinit;
   nMinVal :=CMINinit;
   bInit := FALSE;
END_IF
// Assertions: new min/max values exists:
bValidMaxVal := TRUE;
bValidMinVal := TRUE;
// Filter min/max values
IF (nMaxVal < nInputValue) THEN
   bValidMaxVal := FALSE;
   nMaxVal := nInputValue; // Max value was found
END_IF
IF (nMinVal > nInputValue) THEN
   bValidMinVal := FALSE;
   nMinVal := nInputValue; // Min value was found
END_IF
// Count down, if no new value come in:
IF (bValidMaxVal AND (nMaxValCnt > 0)) THEN
   nMaxValCnt := nMaxValCnt - 1;
END_IF
// Count down, if no new value come in:
IF (bValidMinVal AND (nMinValCnt > 0)) THEN
   nMinValCnt := nMinValCnt - 1;
END_IF
IF ((nMaxValCnt = 0) AND (nMinValCnt = 0)) THEN
   // Consequence: min/max determined
   bInit := TRUE; // Prepare next call
   bRESULT := NOT (nMaxVal = nMinVal); // Sign valid results
ELSE
   bRESULT := FALSE; // Sign still invalid results
END_IF