Click here to Skip to main content
13,047,131 members (60,471 online)
Rate this:
Please Sign up or sign in to vote.
See more: , +
Hi Everyone,

I'm trying to interpret some data from an embedded sensor device into a C++ program. The device uses a numerical format called 1.15 fractional format. This means it transmits 2 hex bytes into a value rangle of ~1 < n < -1.

A description of the format is given in this document ([^]).

I can understand how the format works (for example, negative values have a positive 15th bit) but I'm struggling to implement a convertor in C++ that can identify when the incoming data is negative.

So far I have this function, but it outputs incorrect data for negative numbers

int Convert(BYTE msg0, BYTE msg1, float Target){
	// Combine the 2 bytes 
	unsigned int F = msg0*256 + msg1;
	// display the combined hex bytes and the decimal equivilant
	// These values are correct
	printf("\n\n Combined F = 0x%x \t F = %i",F,F);
	double Ff = (double)F/(32767); // ((2^15)-1) = 32767 = 0x7FFF
	printf("\n Ff = %f",Ff);
	printf("\n Target = %f",Target); 
	return 0;

The Target values are taken from the sensor documentation. As you can see my Positive outputs are pretty close (but not perfect) yet the negative values are way off.


Any suggestions greatfully recieved, I'm a little out of my depth here!
Posted 22-Oct-12 1:48am
Rate this: bad
Please Sign up or sign in to vote.

Solution 1

A couple of changes I would suggest are,
The largest positive number is 0x7fff / 0x8000. So instead of dividing by 32767, we need to divide by 32768.
Also, change the 'unsigned int F' declaration to 'short'. What this will do is give you the 2's complement negative number which you're looking for. Otherwise you can take the 2's complement yourself and get the correct magnitude for negative numbers (numbers starting with the 0x80 byte).

I hope this helps
ad_robot 22-Oct-12 9:31am
Fantastic, those small changes solved it perfectly. I'd actually tried both those changes individually but not together! Many Thanks.
Rate this: bad
Please Sign up or sign in to vote.

Solution 2

According to the documentation signed numbers are represented in the two's complement format. To convert them you may use this:
// Get the absolute number masking out the sign bit
int n = ((msg0 & 0x7F) << 8) + msg1;
// Get negative number:
//  Input  masked  result
//  0x8000 0x0000  -32768
//  ...
//  0xFFFF 0x7FFF  -1
if (msg0 & 0x80)
    n -= 32768; // 0x8000
// Convert to double according to number of fractional bits
double f = (double)n / ((double)(1 << nFrac)); 
ad_robot 22-Oct-12 9:49am
This solution also works excellently. Thank you.

This content, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)

  Print Answers RSS
Top Experts
Last 24hrsThis month

Advertise | Privacy | Mobile
Web02 | 2.8.170713.1 | Last Updated 22 Oct 2012
Copyright © CodeProject, 1999-2017
All Rights Reserved. Terms of Service
Layout: fixed | fluid

CodeProject, 503-250 Ferrand Drive Toronto Ontario, M3C 3G8 Canada +1 416-849-8900 x 100