Apple's System Management Controller uses FPE2 and SP78 as floating-point formats.
While writing a Java library that that interfaces with the SMC, I ported someone's C function to convert read a FPE2-formatted byte array as a float
.
public static float strtof(byte[] bytes, int size, int e) {
int total = 0;
// Add up bits to left of fractional bits
for (int i = 0; i < size; i++) {
if (i == (size - 1))
total += (bytes[i] & 0xff) >> e;
else
total += (bytes[i] & 0xff) << (size - 1 - i) * (8 - e);
}
// Mask fractional bits and divide
return total + (bytes[size - 1] & (1 << e) - 1) / (float) (1 << e);
}
The bytes
and size
parameters come from reading a structure in Apple's SMC interface. The array is a byte[32]
value in a structure, where a second part of the structure states how many of the elements of the array are significant. In the use case, getting fan speed, bytes[0]
and bytes[1]
will be populated with data (the other 30 bytes are ignored) and size
will have a value of 2.
In the given code, the value of e
represents how many rightmost bits out of the size
bytes are for the fractional part. If e
is 2 (such as for FPE2), then the final 2 bits can have values 0, 1, 2, or 3 representing the fractions 0.0, 0.25, 0.5, and 0.75. The remaining leading bits are interpreted as the integer part.
Example input:
- bytes = { 0x00, 0x05, 0x00, 0x00, ... } // First 2 bytes binary 101
- size = 2
- e = 2
Example output: 1.25 // Integer portion is 1, fraction is 1/4.
Did I do it right (assuming arguments are already validated: e
will never be more than 8, and size
will never be more than 4)? Points of concern are order of operation, what happens bitwise when I promote a byte to an int and then shift it.
While this function converts an FPE2 format number, I'm trying to make it a bit more general. A similar format, SP78, is used for temperature. The rightmost 8 bits (divided by 256) are the fractional portion, the left 8 bits are a signed byte. (This method is not intended to handle the signed calculation but this is given as a reference.)