| /** |
| * Copyright © 2020 IBM Corporation |
| * |
| * Licensed under the Apache License, Version 2.0 (the "License"); |
| * you may not use this file except in compliance with the License. |
| * You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, software |
| * distributed under the License is distributed on an "AS IS" BASIS, |
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| * See the License for the specific language governing permissions and |
| * limitations under the License. |
| */ |
| #pragma once |
| |
| #include <cmath> |
| #include <cstdint> |
| #include <string> |
| |
| /** |
| * @namespace pmbus_utils |
| * |
| * Contains utilities for sending PMBus commands over an I2C interface. |
| */ |
| namespace phosphor::power::regulators::pmbus_utils |
| { |
| |
| /* |
| * PMBus command codes. |
| * |
| * The constant names are all uppercase to match the PMBus documentation. |
| * |
| * Only the commands that are currently used by this application are defined. |
| * See the PMBus documentation for all valid command codes. |
| */ |
| const uint8_t VOUT_MODE{0x20u}; |
| const uint8_t VOUT_COMMAND{0x21u}; |
| |
| /** |
| * Sensor data format. |
| */ |
| enum class SensorDataFormat |
| { |
| /** |
| * Linear data format used for values not related to voltage output, such |
| * as output current, input voltage, and temperature. Two byte value with |
| * an 11-bit, two's complement mantissa and a 5-bit, two's complement |
| * exponent. |
| */ |
| linear_11, |
| |
| /** |
| * Linear data format used for values related to voltage output. Two |
| * byte (16-bit), unsigned integer that is raised to the power of an |
| * exponent. The exponent is not stored within the two bytes. |
| */ |
| linear_16 |
| }; |
| |
| /** |
| * Data formats for output voltage. |
| * |
| * These formats are used for commanding and reading output voltage and related |
| * parameters. |
| */ |
| enum class VoutDataFormat |
| { |
| /** |
| * Linear scale that uses a two byte unsigned binary integer with a scaling |
| * factor. |
| */ |
| linear, |
| |
| /** |
| * Format that supports transmitting VID codes. |
| */ |
| vid, |
| |
| /** |
| * Direct format that uses an equation and device supplied coefficients. |
| */ |
| direct, |
| |
| /** |
| * Half-precision floating point format that follows the IEEE-754 standard |
| * for representing magnitudes in 16 bits. |
| */ |
| ieee |
| }; |
| |
| /** |
| * Parse the one byte value of the VOUT_MODE command. |
| * |
| * VOUT_MODE contains a 'mode' field that indicates the data format used for |
| * output voltage values. |
| * |
| * VOUT_MODE also contains a 'parameter' field whose value is dependent on the |
| * data format: |
| * - Linear format: value is an exponent |
| * - VID format: value is a VID code |
| * - IEEE and Direct formats: value is not used |
| * |
| * @param voutModeValue one byte value of VOUT_MODE command |
| * @param format data format from the 'mode' field |
| * @param parameter parameter value from the 'parameter' field |
| */ |
| void parseVoutMode(uint8_t voutModeValue, VoutDataFormat& format, |
| int8_t& parameter); |
| |
| /** |
| * Converts the specified SensorDataFormat value to a string. |
| * |
| * @param format SensorDataFormat value |
| * @return string corresponding to the enum value |
| */ |
| std::string toString(SensorDataFormat format); |
| |
| /** |
| * Converts the specified VoutDataFormat value to string. |
| * |
| * @param format VoutDataFormat format |
| * @return string corresponding to the enum value |
| */ |
| 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 linear data format output voltage value to a volts value. |
| * |
| * This data format consists of the following: |
| * - Two byte value |
| * - 16-bit unsigned mantissa value stored in the two bytes |
| * - 5-bit signed exponent value that is not stored in the two bytes |
| * |
| * @param value linear data format output voltage value |
| * @param exponent exponent value obtained from VOUT_MODE or device |
| * documentation |
| * @return normal decimal number |
| */ |
| inline double convertFromVoutLinear(uint16_t value, int8_t exponent) |
| { |
| // compute value as mantissa * 2^(exponent) |
| double decimal = value * 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: |
| * - Two byte value |
| * - 16-bit unsigned mantissa value stored in the two bytes |
| * - 5-bit signed exponent value that is not stored in the two bytes |
| * |
| * The exponent value is typically obtained from the PMBus VOUT_MODE command |
| * or from the hardware device documentation (data sheet). |
| * |
| * Note that this format differs from the linear data format for values |
| * unrelated to output voltage. |
| * |
| * @param volts volts value to convert; must not be negative |
| * @param exponent 5-bit signed exponent used to convert value |
| * @return linear data format value |
| */ |
| inline uint16_t convertToVoutLinear(double volts, int8_t exponent) |
| { |
| // Obtain mantissa using equation 'mantissa = volts / 2^exponent' |
| double mantissa = volts / std::pow(2.0, static_cast<double>(exponent)); |
| |
| // Return the mantissa value after converting to a rounded uint16_t |
| return static_cast<uint16_t>(std::lround(mantissa)); |
| } |
| |
| } // namespace phosphor::power::regulators::pmbus_utils |