1 /**
2  * Copyright © 2020 IBM Corporation
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *     http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 #pragma once
17 
18 #include <cmath>
19 #include <cstdint>
20 
21 /**
22  * @namespace pmbus_utils
23  *
24  * Contains utilities for sending PMBus commands over an I2C interface.
25  */
26 namespace phosphor::power::regulators::pmbus_utils
27 {
28 
29 /*
30  * PMBus command codes.
31  *
32  * The constant names are all uppercase to match the PMBus documentation.
33  *
34  * Only the commands that are currently used by this application are defined.
35  * See the PMBus documentation for all valid command codes.
36  */
37 const uint8_t VOUT_MODE{0x20u};
38 const uint8_t VOUT_COMMAND{0x21u};
39 
40 /**
41  * Data formats for output voltage.
42  *
43  * These formats are used for commanding and reading output voltage and related
44  * parameters.
45  */
46 enum class VoutDataFormat
47 {
48     /**
49      * Linear scale that uses a two byte unsigned binary integer with a scaling
50      * factor.
51      */
52     linear,
53 
54     /**
55      * Format that supports transmitting VID codes.
56      */
57     vid,
58 
59     /**
60      * Direct format that uses an equation and device supplied coefficients.
61      */
62     direct,
63 
64     /**
65      * Half-precision floating point format that follows the IEEE-754 standard
66      * for representing magnitudes in 16 bits.
67      */
68     ieee
69 };
70 
71 /**
72  * Parse the one byte value of the VOUT_MODE command.
73  *
74  * VOUT_MODE contains a 'mode' field that indicates the data format used for
75  * output voltage values.
76  *
77  * VOUT_MODE also contains a 'parameter' field whose value is dependent on the
78  * data format:
79  *  - Linear format: value is an exponent
80  *  - VID format: value is a VID code
81  *  - IEEE and Direct formats: value is not used
82  *
83  * @param voutModeValue one byte value of VOUT_MODE command
84  * @param format data format from the 'mode' field
85  * @param parameter parameter value from the 'parameter' field
86  */
87 void parseVoutMode(uint8_t voutModeValue, VoutDataFormat& format,
88                    int8_t& parameter);
89 
90 /**
91  * Converts a volts value to the linear data format for output voltage.
92  *
93  * This data format consists of the following:
94  *   - Two byte value
95  *   - 16-bit unsigned mantissa value stored in the two bytes
96  *   - 5-bit signed exponent value that is not stored in the two bytes
97  *
98  * The exponent value is typically obtained from the PMBus VOUT_MODE command
99  * or from the hardware device documentation (data sheet).
100  *
101  * Note that this format differs from the linear data format for values
102  * unrelated to output voltage.
103  *
104  * @param volts volts value to convert; must not be negative
105  * @param exponent 5-bit signed exponent used to convert value
106  * @return linear data format value
107  */
108 inline uint16_t convertToVoutLinear(double volts, int8_t exponent)
109 {
110     // Obtain mantissa using equation 'mantissa = volts / 2^exponent'
111     double mantissa = volts / std::pow(2.0, static_cast<double>(exponent));
112 
113     // Return the mantissa value after converting to a rounded uint16_t
114     return static_cast<uint16_t>(std::lround(mantissa));
115 }
116 
117 } // namespace phosphor::power::regulators::pmbus_utils
118