Double to 48-bit fixed-point number

Here's what I need to do:

Bucket = 0.1 ∗ ((3600 ∗ 1767) / (667 ∗ 50)) = 19.07406

The value to enter in the bucket register should be set as:

Bucket Register = 19.07406 ∗ 2^24
  
The value to set the bucket register is therefore:

High word = 0x000013; Low word = 0x12F5CA

And here's what I have:

double bucketRegister = 19.07406;
int bSum = bucketRegister * pow(2, 24);

char temp[6];
temp[0] = bSum & 0xFF;
temp[1] = (bSum >> 8) & 0xFF;
temp[2] = (bSum >> 16) & 0xFF;
temp[3] = (bSum >> 24) & 0xFF;
temp[4] = (bSum >> 32) & 0xFF;
temp[5] = (bSum >> 40) & 0xFF;

uint32_t lowWord = (temp[2] << 16) + (temp[1] << 8) + temp[0];
uint32_t highWord = (temp[5] << 16) + (temp[4] << 8) + temp[3];

And I get vvvvery close to what the answer should be; 0x000013 and 0x12F598.

I'm losing precision with the bSum variable which has a decimal point after the calculation, but I can't change bSum to a double/float as the compiler throws an error about the >> operator. I'm guessing that I'm following the datasheets workings too literally and there is a way to bypass the multiplication by 224?

What can I do?

Backstory: I need to write two 24 bit words to a MAX78615 which are combined to form a 48-bit fixed-point number with 24 bits for the integer part and 24 bits for the fractional part. Here is the part in the datasheet (bottom of page 31)

Most Arduino's have no double type, double is a synonym for float, and int is 16 bit.

Which board are you compiling for?

Ah sorry, its a Teensy 3.1, but it uses the Arduino IDE and is mostly compatible.

Looks like the extra capability of the Teensy has saved me thus far.

If its easier, assume I have a normal ATMEGA328 instead :slight_smile:

TenderLoins:
Bucket Register = 19.07406 ∗ 2^24

The value to set the bucket register is therefore:

High word = 0x000013; Low word = 0x12F5CA
...
And I get vvvvery close to what the answer should be; 0x000013 and 0x12F598.

So why do you think that 19.07406 ∗ 2^24 is 0x1312F5CA and not 0x1312F598?

0x1312F598 is correct (integer rounding omitted).

Looks like the datasheet is wrong!

Pete

jurs:
So why do you think that 19.07406 ∗ 2^24 is 0x1312F5CA and not 0x1312F598?

0x1312F598 is correct (integer rounding omitted).

headslap well now you mention it, I just did the maths, and it checks out... I was foolishly following the datasheet and realised that I didn't have the same value using my code so figured something was wrong.

Thanks for pointing out that I shouldn't blindly accept what a datasheet says, especially a Maxim one... :slight_smile:

el_supremo:
Looks like the datasheet is wrong!

It's easy to see what they have done.
They did not round the float to = 19.07406, but they used the full result 19.074062968515742128935532233883

19.074062968515742128935532233883 * 2^24 is indeed 0x1312F5CA, as it is written in the datasheet.

So the problem is rounding 19.074062968515742128935532233883 down to 19.07406, which causes the discrepancy.