Change sensorutils to be header-only
In the future sensorutils may need to move to a common repo, so
making it header-only so it can be shared and moved more easily.
Change-Id: I901be5e7721a5fa0f5e308145d55ca3998b11811
Signed-off-by: Jason M. Bills <jason.m.bills@linux.intel.com>
diff --git a/include/sensorutils.hpp b/include/sensorutils.hpp
index 7295a4b..a2f867a 100644
--- a/include/sensorutils.hpp
+++ b/include/sensorutils.hpp
@@ -15,14 +15,170 @@
*/
#pragma once
-#include <cstdint>
+#include <host-ipmid/ipmid-api.h>
+
+#include <cmath>
+#include <iostream>
+#include <phosphor-logging/log.hpp>
namespace ipmi
{
-bool getSensorAttributes(const double maxValue, const double minValue,
- int16_t &mValue, int8_t &rExp, int16_t &bValue,
- int8_t &bExp, bool &bSigned);
-uint8_t scaleIPMIValueFromDouble(const double value, const uint16_t mValue,
- const int8_t rExp, const uint16_t bValue,
- const int8_t bExp, const bool bSigned);
+static constexpr int16_t maxInt10 = 0x1FF;
+static constexpr int16_t minInt10 = -(0x200);
+static constexpr int8_t maxInt4 = 7;
+static constexpr int8_t minInt4 = -8;
+
+static inline bool getSensorAttributes(const double max, const double min,
+ int16_t& mValue, int8_t& rExp,
+ int16_t& bValue, int8_t& bExp,
+ bool& bSigned)
+{
+ // computing y = (10^rRexp) * (Mx + (B*(10^Bexp)))
+ // check for 0, assume always positive
+ double mDouble;
+ double bDouble;
+ if (!(max > min))
+ {
+ phosphor::logging::log<phosphor::logging::level::DEBUG>(
+ "getSensorAttributes: Max must be greater than min");
+ return false;
+ }
+ else
+ {
+ mDouble = (max - min) / 0xFF;
+ }
+ if (!mDouble)
+ {
+ mDouble = 1;
+ }
+
+ if (min < 0)
+ {
+ bSigned = true;
+ bDouble = floor(0.5 + ((max + min) / 2));
+ }
+ else
+ {
+ bSigned = false;
+ bDouble = min;
+ }
+
+ rExp = 0;
+
+ // M too big for 10 bit variable
+ while (mDouble > maxInt10)
+ {
+ if (rExp == maxInt4)
+ {
+ phosphor::logging::log<phosphor::logging::level::DEBUG>(
+ "rExp Too big, Max and Min range too far",
+ phosphor::logging::entry("REXP=%d", rExp));
+ return false;
+ }
+ mDouble /= 10;
+ rExp += 1;
+ }
+
+ // M too small, loop until we lose less than 1 eight bit count of precision
+ while (((mDouble - floor(mDouble)) / mDouble) > (1.0 / 255))
+ {
+ if (rExp == minInt4)
+ {
+ phosphor::logging::log<phosphor::logging::level::DEBUG>(
+ "rExp Too Small, Max and Min range too close");
+ return false;
+ }
+ // check to see if we reached the limit of where we can adjust back the
+ // B value
+ if (bDouble / std::pow(10, rExp + minInt4 - 1) > bDouble)
+ {
+ if (mDouble < 1.0)
+ {
+ phosphor::logging::log<phosphor::logging::level::DEBUG>(
+ "Could not find mValue and B value with enough "
+ "precision.");
+ return false;
+ }
+ break;
+ }
+ // can't multiply M any more, max precision reached
+ else if (mDouble * 10 > maxInt10)
+ {
+ break;
+ }
+ mDouble *= 10;
+ rExp -= 1;
+ }
+
+ bDouble /= std::pow(10, rExp);
+ bExp = 0;
+
+ // B too big for 10 bit variable
+ while (bDouble > maxInt10 || bDouble < minInt10)
+ {
+ if (bExp == maxInt4)
+ {
+ phosphor::logging::log<phosphor::logging::level::DEBUG>(
+ "bExp Too Big, Max and Min range need to be adjusted");
+ return false;
+ }
+ bDouble /= 10;
+ bExp += 1;
+ }
+
+ while (((fabs(bDouble) - floor(fabs(bDouble))) / fabs(bDouble)) >
+ (1.0 / 255))
+ {
+ if (bExp == minInt4)
+ {
+ phosphor::logging::log<phosphor::logging::level::DEBUG>(
+ "bExp Too Small, Max and Min range need to be adjusted");
+ return false;
+ }
+ bDouble *= 10;
+ bExp -= 1;
+ }
+
+ mValue = static_cast<int16_t>(mDouble + 0.5) & maxInt10;
+ bValue = static_cast<int16_t>(bDouble + 0.5) & maxInt10;
+
+ return true;
+}
+
+static inline uint8_t
+ scaleIPMIValueFromDouble(const double value, const uint16_t mValue,
+ const int8_t rExp, const uint16_t bValue,
+ const int8_t bExp, const bool bSigned)
+{
+ uint32_t scaledValue =
+ (value - (bValue * std::pow(10, bExp) * std::pow(10, rExp))) /
+ (mValue * std::pow(10, rExp));
+ if (bSigned)
+ {
+ return static_cast<int8_t>(scaledValue);
+ }
+ else
+ {
+ return static_cast<uint8_t>(scaledValue);
+ }
+}
+
+static inline uint8_t getScaledIPMIValue(const double value, const double max,
+ const double min)
+{
+ int16_t mValue = 0;
+ int8_t rExp = 0;
+ int16_t bValue = 0;
+ int8_t bExp = 0;
+ bool bSigned = 0;
+ bool result = 0;
+
+ result = getSensorAttributes(max, min, mValue, rExp, bValue, bExp, bSigned);
+ if (!result)
+ {
+ return 0xFF;
+ }
+ return scaleIPMIValueFromDouble(value, mValue, rExp, bValue, bExp, bSigned);
+}
+
} // namespace ipmi
\ No newline at end of file