Define a mode for tach sensor timer

Use a single timer on the tach sensors for delaying both nonfunctional
and functional state changes by declaring what mode the timer is in.
Since a fan is either transitioning from a functional state to a
nonfunctional state or vice-versa, enabling the timer in the mode
requested allows the user to define a delay for both of these transition
states.

Tested: Current nonfunctional timer delay operates the same

Change-Id: I0c165355d41d27e1906918953e5226968062ee16
Signed-off-by: Matthew Barth <msbarth@us.ibm.com>
diff --git a/monitor/tach_sensor.cpp b/monitor/tach_sensor.cpp
index 03c34e2..5e985d0 100644
--- a/monitor/tach_sensor.cpp
+++ b/monitor/tach_sensor.cpp
@@ -15,6 +15,7 @@
  */
 #include <experimental/filesystem>
 #include <phosphor-logging/log.hpp>
+#include <phosphor-logging/elog.hpp>
 #include "fan.hpp"
 #include "sdbusplus.hpp"
 #include "tach_sensor.hpp"
@@ -32,6 +33,8 @@
 constexpr auto FAN_VALUE_PROPERTY = "Value";
 
 using namespace std::experimental::filesystem;
+using InternalFailure = sdbusplus::xyz::openbmc_project::Common::
+                            Error::InternalFailure;
 
 /**
  * @brief Helper function to read a property
@@ -84,6 +87,7 @@
     _factor(factor),
     _offset(offset),
     _timeout(timeout),
+    _timerMode(TimerMode::func),
     _timer(events, [this, &fan](){ fan.timerExpired(*this); })
 {
     // Start from a known state of functional
@@ -212,12 +216,45 @@
    _fan.tachChanged(*this);
 }
 
+void TachSensor::startTimer(TimerMode mode)
+{
+    if (!timerRunning())
+    {
+        _timer.start(
+                getDelay(mode),
+                util::Timer::TimerType::oneshot);
+        _timerMode = mode;
+    }
+    else
+    {
+        if (mode != _timerMode)
+        {
+            _timer.stop();
+            _timer.start(
+                    getDelay(mode),
+                    util::Timer::TimerType::oneshot);
+            _timerMode = mode;
+        }
+    }
+}
 
-std::chrono::microseconds TachSensor::getTimeout()
+std::chrono::microseconds TachSensor::getDelay(TimerMode mode)
 {
     using namespace std::chrono;
 
-    return duration_cast<microseconds>(seconds(_timeout));
+    switch(mode)
+    {
+        case TimerMode::nonfunc :
+                return duration_cast<microseconds>(seconds(_timeout));
+        case TimerMode::func :
+                return duration_cast<microseconds>(seconds(_funcDelay));
+        default :
+                // Log an internal error for undefined timer mode
+                log<level::ERR>("Undefined timer mode",
+                        entry("TIMER_MODE=%u", mode));
+                elog<InternalFailure>();
+                return duration_cast<microseconds>(seconds(0));
+    }
 }
 
 void TachSensor::updateInventory(bool functional)