[563446] Replaced E_STOPWATCH with a pure basic FB

With the new NOW_MONOTONIC functions it is now possible to implement the
E_STOPWATCH as pure basic FB with just ST algorithms.

Bug: https://bugs.eclipse.org/bugs/show_bug.cgi?id=563446
Change-Id: Iea9de2895325c8427230465b85133c408d4749c9
Signed-off-by: Alois Zoitl <alois.zoitl@gmx.at>
diff --git a/src/modules/utils/CMakeLists.txt b/src/modules/utils/CMakeLists.txt
index 2c242c4..c139fd3 100644
--- a/src/modules/utils/CMakeLists.txt
+++ b/src/modules/utils/CMakeLists.txt
@@ -16,16 +16,7 @@
 # FORTE UTILITY FBs
 #############################################################################
 
-if(NOT "${FORTE_ARCHITECTURE}" STREQUAL "VxWorks") #the compiler used to test vxworks doesn't support ++11
-  if(CYGWIN)
-    forte_add_definition("-std=gnu++11") 
-  else(CYGWIN)
-    forte_add_definition("-std=c++11")
-  endif(CYGWIN)
-
-  forte_add_sourcefile_hcpp(E_STOPWATCH)
-endif(NOT "${FORTE_ARCHITECTURE}" STREQUAL "VxWorks")
-
+forte_add_sourcefile_hcpp(E_STOPWATCH)
 forte_add_sourcefile_hcpp(OUT_ANY_CONSOLE GEN_F_MUX GEN_CSV_WRITER GEN_APPEND_STRING)
 forte_add_sourcefile_hcpp(GEN_ARRAY2VALUES GEN_VALUES2ARRAY GEN_ARRAY2ARRAY GET_AT_INDEX SET_AT_INDEX)
 forte_add_sourcefile_hcpp(FB_RANDOM GET_STRUCT_VALUE)
diff --git a/src/modules/utils/E_STOPWATCH.cpp b/src/modules/utils/E_STOPWATCH.cpp
index 55c9666..646a5f5 100644
--- a/src/modules/utils/E_STOPWATCH.cpp
+++ b/src/modules/utils/E_STOPWATCH.cpp
@@ -1,91 +1,111 @@
-/*******************************************************************************

- * Copyright (c) 2018 fortiss GmbH

+/*******************************************************************************
+ * Copyright (c) 2018 fortiss GmbH
+ *               2020 Johannes Kepler University Linz
+ * 
  * This program and the accompanying materials are made available under the
  * terms of the Eclipse Public License 2.0 which is available at
  * http://www.eclipse.org/legal/epl-2.0.
  *
- * SPDX-License-Identifier: EPL-2.0

- *

- * Contributors:

- *   Ben Schneider

- *   - initial API and implementation and/or initial documentation

- *******************************************************************************/

-

-#include "E_STOPWATCH.h"

-#ifdef FORTE_ENABLE_GENERATED_SOURCE_CPP

-#include "E_STOPWATCH_gen.cpp"

-#endif

-

-DEFINE_FIRMWARE_FB(FORTE_E_STOPWATCH, g_nStringIdE_STOPWATCH)

-

-const CStringDictionary::TStringId FORTE_E_STOPWATCH::scm_anDataOutputNames[] = {g_nStringIdTD};

-

-const CStringDictionary::TStringId FORTE_E_STOPWATCH::scm_anDataOutputTypeIds[] = {g_nStringIdTIME};

-

-const TForteInt16 FORTE_E_STOPWATCH::scm_anEIWithIndexes[] = {-1, -1};

-const CStringDictionary::TStringId FORTE_E_STOPWATCH::scm_anEventInputNames[] = {g_nStringIdSTART, g_nStringIdSTOP};

-

-const TDataIOID FORTE_E_STOPWATCH::scm_anEOWith[] = {0, 255};

-const TForteInt16 FORTE_E_STOPWATCH::scm_anEOWithIndexes[] = {0, -1};

-const CStringDictionary::TStringId FORTE_E_STOPWATCH::scm_anEventOutputNames[] = {g_nStringIdEO};

-

-const SFBInterfaceSpec FORTE_E_STOPWATCH::scm_stFBInterfaceSpec = {

-    2,  scm_anEventInputNames,  0,  scm_anEIWithIndexes,

-    1,  scm_anEventOutputNames,  scm_anEOWith, scm_anEOWithIndexes,  0,  0, 0,

-    1,  scm_anDataOutputNames, scm_anDataOutputTypeIds,

-    0, 0

-};

-

-void FORTE_E_STOPWATCH::writeElapsedTimeToTD(){

-

-  mCurrentTime = static_cast<int>(chrono::duration_cast<chrono::microseconds>(m_end - m_begin).count());

-  TD().setFromMicroSeconds(mCurrentTime);

-}

-

-void FORTE_E_STOPWATCH::enterStateSTART(void){

-  m_nECCState = scm_nStateSTART;

-}

-

-void FORTE_E_STOPWATCH::enterStateMeasure(void){

-  m_nECCState = scm_nStateMeasure;

-  m_begin = chrono::high_resolution_clock::now();

-}

-

-void FORTE_E_STOPWATCH::enterStateStopped(void){

-  m_nECCState = scm_nStateStopped;

-  m_end = chrono::high_resolution_clock::now();

-  writeElapsedTimeToTD();

-  sendOutputEvent( scm_nEventEOID);

-}

-

-void FORTE_E_STOPWATCH::executeEvent(int pa_nEIID){

-  bool bTransitionCleared;

-  do{

-    bTransitionCleared = true;

-    switch(m_nECCState){

-      case scm_nStateSTART:

-        if(scm_nEventSTARTID == pa_nEIID)

-          enterStateMeasure();

-        else

-          bTransitionCleared  = false; //no transition cleared

-        break;

-      case scm_nStateMeasure:

-        if(scm_nEventSTOPID == pa_nEIID)

-          enterStateStopped();

-        else

-          bTransitionCleared  = false; //no transition cleared

-        break;

-      case scm_nStateStopped:

-        if(1)

-          enterStateSTART();

-        else

-          bTransitionCleared  = false; //no transition cleared

-        break;

-      default:

-        DEVLOG_ERROR("The state is not in the valid range! The state value is: %d. The max value can be: 2.", m_nECCState.operator TForteUInt16 ());

-        m_nECCState = 0; //0 is always the initial state

-        break;

-    }

-    pa_nEIID = cg_nInvalidEventID;  // we have to clear the event after the first check in order to ensure correct behavior

-  }while(bTransitionCleared);

-}

+ * SPDX-License-Identifier: EPL-2.0
+ *
+ * Contributors:
+ *   Ben Schneider - initial API and implementation and/or initial documentation
+ *   Alois Zoitl   - Changed to a full basic FB implementation utilizing the new 
+ *                   NOW_MONOTONIC function
+ *******************************************************************************/
+
+#include "E_STOPWATCH.h"
+#ifdef FORTE_ENABLE_GENERATED_SOURCE_CPP
+#include "E_STOPWATCH_gen.cpp"
+#endif
+
+
+DEFINE_FIRMWARE_FB(FORTE_E_STOPWATCH, g_nStringIdE_STOPWATCH)
+
+
+const CStringDictionary::TStringId FORTE_E_STOPWATCH::scm_anDataOutputNames[] = {g_nStringIdTD};
+
+const CStringDictionary::TStringId FORTE_E_STOPWATCH::scm_anDataOutputTypeIds[] = {g_nStringIdTIME};
+
+const TDataIOID FORTE_E_STOPWATCH::scm_anEIWith[] = {};
+const TForteInt16 FORTE_E_STOPWATCH::scm_anEIWithIndexes[] = {-1, -1};
+const CStringDictionary::TStringId FORTE_E_STOPWATCH::scm_anEventInputNames[] = {g_nStringIdSTART, g_nStringIdSTOP};
+
+const TDataIOID FORTE_E_STOPWATCH::scm_anEOWith[] = {0, 255};
+const TForteInt16 FORTE_E_STOPWATCH::scm_anEOWithIndexes[] = {0};
+const CStringDictionary::TStringId FORTE_E_STOPWATCH::scm_anEventOutputNames[] = {g_nStringIdEO};
+
+
+const SFBInterfaceSpec FORTE_E_STOPWATCH::scm_stFBInterfaceSpec = {
+  2, scm_anEventInputNames, scm_anEIWith, scm_anEIWithIndexes,
+  1, scm_anEventOutputNames, scm_anEOWith, scm_anEOWithIndexes,
+  0, 0, 0,
+  1, scm_anDataOutputNames, scm_anDataOutputTypeIds,
+  0, 0
+};
+
+const CStringDictionary::TStringId FORTE_E_STOPWATCH::scm_anInternalsNames[] = {g_nStringIdstartTime};
+const CStringDictionary::TStringId FORTE_E_STOPWATCH::scm_anInternalsTypeIds[] = {g_nStringIdTIME};
+
+const SInternalVarsInformation FORTE_E_STOPWATCH::scm_stInternalVars = {1, scm_anInternalsNames, scm_anInternalsTypeIds};
+
+
+
+void FORTE_E_STOPWATCH::alg_captureStartTime(void) {
+  st_startTime() = NOW_MONOTONIC();
+}
+
+void FORTE_E_STOPWATCH::alg_calcDiff(void) {
+  st_TD() = (NOW_MONOTONIC() - st_startTime());
+}
+
+
+void FORTE_E_STOPWATCH::enterStateSTART(void) {
+  m_nECCState = scm_nStateSTART;
+}
+
+void FORTE_E_STOPWATCH::enterStateMeasure(void) {
+  m_nECCState = scm_nStateMeasure;
+  alg_captureStartTime();
+}
+
+void FORTE_E_STOPWATCH::enterStateSTOP(void) {
+  m_nECCState = scm_nStateSTOP;
+  alg_calcDiff();
+  sendOutputEvent(scm_nEventEOID);
+}
+
+
+void FORTE_E_STOPWATCH::executeEvent(int pa_nEIID){
+  bool bTransitionCleared;
+  do {
+    bTransitionCleared = true;
+    switch(m_nECCState) {
+      case scm_nStateSTART:
+        if(scm_nEventSTARTID == pa_nEIID)
+          enterStateMeasure();
+        else
+          bTransitionCleared  = false; //no transition cleared
+        break;
+      case scm_nStateMeasure:
+        if(scm_nEventSTOPID == pa_nEIID)
+          enterStateSTOP();
+        else
+          bTransitionCleared  = false; //no transition cleared
+        break;
+      case scm_nStateSTOP:
+        if(1)
+          enterStateSTART();
+        else
+          bTransitionCleared  = false; //no transition cleared
+        break;
+      default:
+        DEVLOG_ERROR("The state is not in the valid range! The state value is: %d. The max value can be: 3.", m_nECCState.operator TForteUInt16 ());
+        m_nECCState = 0; // 0 is always the initial state
+        break;
+    }
+    pa_nEIID = cg_nInvalidEventID; // we have to clear the event after the first check in order to ensure correct behavior
+  } while(bTransitionCleared);
+}
+
+
diff --git a/src/modules/utils/E_STOPWATCH.h b/src/modules/utils/E_STOPWATCH.h
index ed39b80..b443e15 100644
--- a/src/modules/utils/E_STOPWATCH.h
+++ b/src/modules/utils/E_STOPWATCH.h
@@ -1,71 +1,87 @@
-/*******************************************************************************

- * Copyright (c) 2018 fortiss GmbH

+/*******************************************************************************
+ * Copyright (c) 2018 fortiss GmbH
+ *               2020 Johannes Kepler University Linz
+ * 
  * This program and the accompanying materials are made available under the
  * terms of the Eclipse Public License 2.0 which is available at
  * http://www.eclipse.org/legal/epl-2.0.
  *
- * SPDX-License-Identifier: EPL-2.0

- *

- * Contributors:

- *   Ben Schneider

- *   - initial API and implementation and/or initial documentation

- *******************************************************************************/

-

-#ifndef _E_STOPWATCH_H_

-#define _E_STOPWATCH_H_

-

-#include <basicfb.h>

-#include <forte_time.h>

-

-#include <chrono>

-using namespace std;

-

-class FORTE_E_STOPWATCH: public CBasicFB{

-  DECLARE_FIRMWARE_FB(FORTE_E_STOPWATCH)

-

-private:

-  chrono::time_point <chrono::high_resolution_clock> m_begin, m_end;

-  int mCurrentTime = 0;

-

-  static const CStringDictionary::TStringId scm_anDataOutputNames[];

-  static const CStringDictionary::TStringId scm_anDataOutputTypeIds[];

-  CIEC_TIME &TD() {

-    return *static_cast<CIEC_TIME*>(getDO(0));

-  };

-

-  static const TEventID scm_nEventSTARTID = 0;

-  static const TEventID scm_nEventSTOPID = 1;

-  static const TForteInt16 scm_anEIWithIndexes[];

-  static const CStringDictionary::TStringId scm_anEventInputNames[];

-

-  static const TEventID scm_nEventEOID = 0;

-  static const TForteInt16 scm_anEOWithIndexes[];

-  static const TDataIOID scm_anEOWith[];

-  static const CStringDictionary::TStringId scm_anEventOutputNames[];

-

-  static const SFBInterfaceSpec scm_stFBInterfaceSpec;

-

-  FORTE_BASIC_FB_DATA_ARRAY(1, 0, 1, 0, 0);

-  static const TForteInt16 scm_nStateSTART = 0;

-  static const TForteInt16 scm_nStateMeasure = 1;

-  static const TForteInt16 scm_nStateStopped = 2;

-

-  void enterStateSTART(void);

-  void enterStateMeasure(void);

-  void enterStateStopped(void);

-

-  virtual void executeEvent(int pa_nEIID);

-

-  void writeElapsedTimeToTD(void);

-

-public:

-  FORTE_E_STOPWATCH(CStringDictionary::TStringId pa_nInstanceNameId, CResource *pa_poSrcRes) :

-    CBasicFB(pa_poSrcRes, &scm_stFBInterfaceSpec, pa_nInstanceNameId,

-        0, m_anFBConnData, m_anFBVarsData){

-  };

-

-  virtual ~FORTE_E_STOPWATCH(){};

-

-};

-

-#endif //close the ifdef sequence from the beginning of the file

+ * SPDX-License-Identifier: EPL-2.0
+ *
+ * Contributors:
+ *   Ben Schneider - initial API and implementation and/or initial documentation
+ *   Alois Zoitl   - Changed to a full basic FB implementation utilizing the new 
+ *                   NOW_MONOTONIC function
+ *******************************************************************************/
+
+#ifndef _E_STOPWATCH_H_
+#define _E_STOPWATCH_H_
+
+#include "basicfb.h"
+#include "forte_time.h"
+#include "forte_array_at.h"
+
+
+class FORTE_E_STOPWATCH: public CBasicFB {
+  DECLARE_FIRMWARE_FB(FORTE_E_STOPWATCH)
+
+private:
+  
+  static const CStringDictionary::TStringId scm_anDataOutputNames[];
+  static const CStringDictionary::TStringId scm_anDataOutputTypeIds[];
+  
+  static const TEventID scm_nEventSTARTID = 0;
+  static const TEventID scm_nEventSTOPID = 1;
+  
+  static const TDataIOID scm_anEIWith[];
+  static const TForteInt16 scm_anEIWithIndexes[];
+  static const CStringDictionary::TStringId scm_anEventInputNames[];
+  
+  static const TEventID scm_nEventEOID = 0;
+  
+  static const TDataIOID scm_anEOWith[];
+  static const TForteInt16 scm_anEOWithIndexes[];
+  static const CStringDictionary::TStringId scm_anEventOutputNames[];
+  
+
+  static const SFBInterfaceSpec scm_stFBInterfaceSpec;
+  
+  static const CStringDictionary::TStringId scm_anInternalsNames[];
+  static const CStringDictionary::TStringId scm_anInternalsTypeIds[];
+  static const SInternalVarsInformation scm_stInternalVars;
+
+  CIEC_TIME &st_TD() {
+    return *static_cast<CIEC_TIME*>(getDO(0));
+  }
+  
+  CIEC_TIME &st_startTime() {
+    return *static_cast<CIEC_TIME*>(getVarInternal(0));
+  }
+  
+
+  void alg_captureStartTime(void);
+  void alg_calcDiff(void);
+
+  static const TForteInt16 scm_nStateSTART = 0;
+  static const TForteInt16 scm_nStateMeasure = 1;
+  static const TForteInt16 scm_nStateSTOP = 2;
+  
+  void enterStateSTART(void);
+  void enterStateMeasure(void);
+  void enterStateSTOP(void);
+
+  virtual void executeEvent(int pa_nEIID);
+
+  FORTE_BASIC_FB_DATA_ARRAY(1, 0, 1, 1, 0);
+
+public:
+  FORTE_E_STOPWATCH(CStringDictionary::TStringId pa_nInstanceNameId, CResource *pa_poSrcRes) :
+       CBasicFB(pa_poSrcRes, &scm_stFBInterfaceSpec, pa_nInstanceNameId, &scm_stInternalVars, m_anFBConnData, m_anFBVarsData) {
+  };
+
+  virtual ~FORTE_E_STOPWATCH(){};
+};
+
+#endif // _E_STOPWATCH_H_
+
+