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 #include "pmbus_utils.hpp"
17 
18 #include <cstdint>
19 
20 #include <gtest/gtest.h>
21 
22 using namespace phosphor::power::regulators;
23 
24 TEST(PMBusUtilsTests, ParseVoutMode)
25 {
26     uint8_t voutModeValue;
27     pmbus_utils::VoutDataFormat format;
28     int8_t parameter;
29 
30     // Linear format: Exponent is negative: 0b1'1111
31     voutModeValue = 0b0001'1111u;
32     pmbus_utils::parseVoutMode(voutModeValue, format, parameter);
33     EXPECT_EQ(format, pmbus_utils::VoutDataFormat::linear);
34     EXPECT_EQ(parameter, -1);
35 
36     // Linear format: Exponent is negative: 0b1'0000
37     voutModeValue = 0b1001'0000u;
38     pmbus_utils::parseVoutMode(voutModeValue, format, parameter);
39     EXPECT_EQ(format, pmbus_utils::VoutDataFormat::linear);
40     EXPECT_EQ(parameter, -16);
41 
42     // Linear format: Exponent is positive: 0b0'1111
43     voutModeValue = 0b1000'1111u;
44     pmbus_utils::parseVoutMode(voutModeValue, format, parameter);
45     EXPECT_EQ(format, pmbus_utils::VoutDataFormat::linear);
46     EXPECT_EQ(parameter, 15);
47 
48     // Linear format: Exponent is positive: 0b0'0001
49     voutModeValue = 0b0000'0001u;
50     pmbus_utils::parseVoutMode(voutModeValue, format, parameter);
51     EXPECT_EQ(format, pmbus_utils::VoutDataFormat::linear);
52     EXPECT_EQ(parameter, 1);
53 
54     // Linear format: Exponent is zero: 0b0'0000
55     voutModeValue = 0b0000'0000u;
56     pmbus_utils::parseVoutMode(voutModeValue, format, parameter);
57     EXPECT_EQ(format, pmbus_utils::VoutDataFormat::linear);
58     EXPECT_EQ(parameter, 0);
59 
60     // VID format: VID code is 0b1'1111
61     voutModeValue = 0b0011'1111u;
62     pmbus_utils::parseVoutMode(voutModeValue, format, parameter);
63     EXPECT_EQ(format, pmbus_utils::VoutDataFormat::vid);
64     EXPECT_EQ(parameter, 31);
65 
66     // VID format: VID code is 0b1'0000
67     voutModeValue = 0b1011'0000u;
68     pmbus_utils::parseVoutMode(voutModeValue, format, parameter);
69     EXPECT_EQ(format, pmbus_utils::VoutDataFormat::vid);
70     EXPECT_EQ(parameter, 16);
71 
72     // VID format: VID code is 0b0'1111
73     voutModeValue = 0b1010'1111u;
74     pmbus_utils::parseVoutMode(voutModeValue, format, parameter);
75     EXPECT_EQ(format, pmbus_utils::VoutDataFormat::vid);
76     EXPECT_EQ(parameter, 15);
77 
78     // VID format: VID code is 0b0'0001
79     voutModeValue = 0b0010'0001u;
80     pmbus_utils::parseVoutMode(voutModeValue, format, parameter);
81     EXPECT_EQ(format, pmbus_utils::VoutDataFormat::vid);
82     EXPECT_EQ(parameter, 1);
83 
84     // VID format: VID code is 0b0'0000
85     voutModeValue = 0b1010'0000u;
86     pmbus_utils::parseVoutMode(voutModeValue, format, parameter);
87     EXPECT_EQ(format, pmbus_utils::VoutDataFormat::vid);
88     EXPECT_EQ(parameter, 0);
89 
90     // Direct format
91     voutModeValue = 0b1100'0000u;
92     pmbus_utils::parseVoutMode(voutModeValue, format, parameter);
93     EXPECT_EQ(format, pmbus_utils::VoutDataFormat::direct);
94     EXPECT_EQ(parameter, 0);
95 
96     // IEEE format
97     voutModeValue = 0b0110'0000u;
98     pmbus_utils::parseVoutMode(voutModeValue, format, parameter);
99     EXPECT_EQ(format, pmbus_utils::VoutDataFormat::ieee);
100     EXPECT_EQ(parameter, 0);
101 }
102 
103 TEST(PMBusUtilsTests, ToString)
104 {
105     // Sensor data format: SensorDataFormat::linear_11
106     {
107         pmbus_utils::SensorDataFormat format =
108             pmbus_utils::SensorDataFormat::linear_11;
109         EXPECT_EQ(pmbus_utils::toString(format), "linear_11");
110     }
111 
112     // Sensor data format: SensorDataFormat::linear_16
113     {
114         pmbus_utils::SensorDataFormat format =
115             pmbus_utils::SensorDataFormat::linear_16;
116         EXPECT_EQ(pmbus_utils::toString(format), "linear_16");
117     }
118 
119     // Vout data format: VoutDataFormat::linear
120     {
121         pmbus_utils::VoutDataFormat format =
122             pmbus_utils::VoutDataFormat::linear;
123         EXPECT_EQ(pmbus_utils::toString(format), "linear");
124     }
125 
126     // Vout data format: VoutDataFormat::vid
127     {
128         pmbus_utils::VoutDataFormat format = pmbus_utils::VoutDataFormat::vid;
129         EXPECT_EQ(pmbus_utils::toString(format), "vid");
130     }
131 
132     // Vout data format: VoutDataFormat::direct
133     {
134         pmbus_utils::VoutDataFormat format =
135             pmbus_utils::VoutDataFormat::direct;
136         EXPECT_EQ(pmbus_utils::toString(format), "direct");
137     }
138 
139     // Vout data format: VoutDataFormat::ieee
140     {
141         pmbus_utils::VoutDataFormat format = pmbus_utils::VoutDataFormat::ieee;
142         EXPECT_EQ(pmbus_utils::toString(format), "ieee");
143     }
144 }
145 
146 TEST(PMBusUtilsTests, ConvertFromLinear)
147 {
148     uint16_t value;
149 
150     // Minimum possible exponent value: -16
151     // mantissa : 511, exponent : -16, decimal = 511 * 2^-16 =
152     // 0.0077972412109375
153     value = 0x81ff;
154     EXPECT_DOUBLE_EQ(pmbus_utils::convertFromLinear(value), 0.0077972412109375);
155 
156     // Maximum possible exponent value: 15
157     // mantissa : 2, exponent : 15, decimal = 2 * 2^15 = 65536
158     value = 0x7802;
159     EXPECT_DOUBLE_EQ(pmbus_utils::convertFromLinear(value), 65536);
160 
161     // Minimum possible mantissa value: -1024
162     // mantissa : -1024, exponent : 1, decimal = -1024 * 2^1 = -2048
163     value = 0x0c00;
164     EXPECT_DOUBLE_EQ(pmbus_utils::convertFromLinear(value), -2048);
165 
166     // Maximum possible mantissa value: 1023
167     // mantissa : 1023, exponent : -11, decimal = 1023 * 2^-11 = 0.49951171875
168     value = 0xabff;
169     EXPECT_DOUBLE_EQ(pmbus_utils::convertFromLinear(value), 0.49951171875);
170 
171     // Exponent = 0, mantissa > 0
172     // mantissa : 1, exponent : 0, decimal = 1 * 2^0 = 1
173     value = 0x0001;
174     EXPECT_DOUBLE_EQ(pmbus_utils::convertFromLinear(value), 1);
175 
176     // Exponent > 0, mantissa > 0
177     // mantissa : 2, exponent : 1, decimal = 2 * 2^1 = 4
178     value = 0x0802;
179     EXPECT_DOUBLE_EQ(pmbus_utils::convertFromLinear(value), 4);
180 
181     // Exponent < 0, mantissa > 0
182     // mantissa : 15, exponent : -1, decimal = 15 * 2^-1 = 7.5
183     value = 0xf80f;
184     EXPECT_DOUBLE_EQ(pmbus_utils::convertFromLinear(value), 7.5);
185 
186     // Exponent > 0, mantissa = 0
187     // mantissa : 0, exponent : 3, decimal = 0 * 2^3 = 0
188     value = 0x1800;
189     EXPECT_DOUBLE_EQ(pmbus_utils::convertFromLinear(value), 0);
190 
191     // Exponent > 0, mantissa < 0
192     // mantissa : -2, exponent : 3, decimal = -2 * 2^3 = -16
193     value = 0x1ffe;
194     EXPECT_DOUBLE_EQ(pmbus_utils::convertFromLinear(value), -16);
195 }
196 
197 TEST(PMBusUtilsTests, ConvertFromVoutLinear)
198 {
199     uint16_t value;
200     int8_t exponent;
201 
202     // mantissa : 1, exponent : 2, decimal = 1 * 2^2 = 4
203     value = 0x0001;
204     exponent = 2;
205     EXPECT_DOUBLE_EQ(pmbus_utils::convertFromVoutLinear(value, exponent), 4);
206 
207     // mantissa : 15, exponent : 0, decimal = 15 * 2^0 = 15
208     value = 0x000f;
209     exponent = 0;
210     EXPECT_DOUBLE_EQ(pmbus_utils::convertFromVoutLinear(value, exponent), 15);
211 
212     // mantissa : 255, exponent : -3, decimal = 255 * 2^-3 = 31.875
213     value = 0x00ff;
214     exponent = -3;
215     EXPECT_DOUBLE_EQ(pmbus_utils::convertFromVoutLinear(value, exponent),
216                      31.875);
217 
218     // mantissa : 0, exponent : 10, decimal = 0 * 2^10 = 0
219     value = 0x0000;
220     exponent = 10;
221     EXPECT_DOUBLE_EQ(pmbus_utils::convertFromVoutLinear(value, exponent), 0);
222 }
223 
224 TEST(PMBusUtilsTests, ConvertToVoutLinear)
225 {
226     double volts;
227     int8_t exponent;
228 
229     // Exponent > 0: Value is not rounded up
230     volts = 13.9;
231     exponent = 2;
232     // 13.9 / 2^2 == 3.475 = 3
233     EXPECT_EQ(pmbus_utils::convertToVoutLinear(volts, exponent), 3);
234 
235     // Exponent > 0: Value is rounded up
236     volts = 14.0;
237     exponent = 2;
238     // 14.0 / 2^2 == 3.5 = 4
239     EXPECT_EQ(pmbus_utils::convertToVoutLinear(volts, exponent), 4);
240 
241     // Exponent = 0: Value is not rounded up
242     volts = 2.49;
243     exponent = 0;
244     // 2.49 / 2^0 == 2.49 = 2
245     EXPECT_EQ(pmbus_utils::convertToVoutLinear(volts, exponent), 2);
246 
247     // Exponent = 0: Value is rounded up
248     volts = 2.51;
249     exponent = 0;
250     // 2.51 / 2^0 == 2.51 = 3
251     EXPECT_EQ(pmbus_utils::convertToVoutLinear(volts, exponent), 3);
252 
253     // Exponent < 0: Value is not rounded up
254     volts = 1.32613;
255     exponent = -8;
256     // 1.32613 / 2^-8 == 339.48928 == 339
257     EXPECT_EQ(pmbus_utils::convertToVoutLinear(volts, exponent), 339);
258 
259     // Exponent < 0: Value is rounded up
260     volts = 1.32618;
261     exponent = -8;
262     // 1.32618 / 2^-8 == 339.50208 == 340
263     EXPECT_EQ(pmbus_utils::convertToVoutLinear(volts, exponent), 340);
264 }
265