regulators: Add convertFromLinear for sensor monitoring
Add convertFromLinear function.
The function is for converting from linear_11 format to a normal
decimal number.
Signed-off-by: Bob King <Bob_King@wistron.com>
Change-Id: I6bdeaf8e9d9a26ae144c9db3494f758fd9eb48ee
diff --git a/phosphor-regulators/src/pmbus_utils.hpp b/phosphor-regulators/src/pmbus_utils.hpp
index 5e2e270..93d2dce 100644
--- a/phosphor-regulators/src/pmbus_utils.hpp
+++ b/phosphor-regulators/src/pmbus_utils.hpp
@@ -185,6 +185,45 @@
std::string toString(VoutDataFormat format);
/**
+ * Converts a linear data format value to a double value.
+ *
+ * This data format consists of the following:
+ * - Two byte value
+ * - 11-bit two's complement mantissa value stored in the two bytes
+ * - 5-bit two's complement exponent value stored in the two bytes
+ *
+ * @param value linear data format value
+ * @return double value
+ */
+inline double convertFromLinear(uint16_t value)
+{
+ // extract exponent from most significant 5 bits
+ uint8_t exponentField = value >> 11;
+
+ // extract mantissa from least significant 11 bits
+ uint16_t mantissaField = value & 0x7FFu;
+
+ // sign extend exponent
+ if (exponentField > 0x0Fu)
+ {
+ exponentField |= 0xE0u;
+ }
+
+ // sign extend mantissa
+ if (mantissaField > 0x03FFu)
+ {
+ mantissaField |= 0xF800u;
+ }
+
+ int8_t exponent = static_cast<int8_t>(exponentField);
+ int16_t mantissa = static_cast<int16_t>(mantissaField);
+
+ // compute value as mantissa * 2^(exponent)
+ double decimal = mantissa * std::pow(2.0, exponent);
+ return decimal;
+}
+
+/**
* Converts a volts value to the linear data format for output voltage.
*
* This data format consists of the following:
diff --git a/phosphor-regulators/test/pmbus_utils_tests.cpp b/phosphor-regulators/test/pmbus_utils_tests.cpp
index 4aab7db..96e10bd 100644
--- a/phosphor-regulators/test/pmbus_utils_tests.cpp
+++ b/phosphor-regulators/test/pmbus_utils_tests.cpp
@@ -203,6 +203,57 @@
}
}
+TEST(PMBusUtilsTests, ConvertFromLinear)
+{
+ uint16_t value;
+
+ // Minimum possible exponent value: -16
+ // mantissa : 511, exponent : -16, decimal = 511 * 2^-16 =
+ // 0.0077972412109375
+ value = 0x81ff;
+ EXPECT_DOUBLE_EQ(pmbus_utils::convertFromLinear(value), 0.0077972412109375);
+
+ // Maximum possible exponent value: 15
+ // mantissa : 2, exponent : 15, decimal = 2 * 2^15 = 65536
+ value = 0x7802;
+ EXPECT_DOUBLE_EQ(pmbus_utils::convertFromLinear(value), 65536);
+
+ // Minimum possible mantissa value: -1024
+ // mantissa : -1024, exponent : 1, decimal = -1024 * 2^1 = -2048
+ value = 0x0c00;
+ EXPECT_DOUBLE_EQ(pmbus_utils::convertFromLinear(value), -2048);
+
+ // Maximum possible mantissa value: 1023
+ // mantissa : 1023, exponent : -11, decimal = 1023 * 2^-11 = 0.49951171875
+ value = 0xabff;
+ EXPECT_DOUBLE_EQ(pmbus_utils::convertFromLinear(value), 0.49951171875);
+
+ // Exponent = 0, mantissa > 0
+ // mantissa : 1, exponent : 0, decimal = 1 * 2^0 = 1
+ value = 0x0001;
+ EXPECT_DOUBLE_EQ(pmbus_utils::convertFromLinear(value), 1);
+
+ // Exponent > 0, mantissa > 0
+ // mantissa : 2, exponent : 1, decimal = 2 * 2^1 = 4
+ value = 0x0802;
+ EXPECT_DOUBLE_EQ(pmbus_utils::convertFromLinear(value), 4);
+
+ // Exponent < 0, mantissa > 0
+ // mantissa : 15, exponent : -1, decimal = 15 * 2^-1 = 7.5
+ value = 0xf80f;
+ EXPECT_DOUBLE_EQ(pmbus_utils::convertFromLinear(value), 7.5);
+
+ // Exponent > 0, mantissa = 0
+ // mantissa : 0, exponent : 3, decimal = 0 * 2^3 = 0
+ value = 0x1800;
+ EXPECT_DOUBLE_EQ(pmbus_utils::convertFromLinear(value), 0);
+
+ // Exponent > 0, mantissa < 0
+ // mantissa : -2, exponent : 3, decimal = -2 * 2^3 = -16
+ value = 0x1ffe;
+ EXPECT_DOUBLE_EQ(pmbus_utils::convertFromLinear(value), -16);
+}
+
TEST(PMBusUtilsTests, ConvertToVoutLinear)
{
double volts;