Click here to Skip to main content
15,885,309 members
Please Sign up or sign in to vote.
0.00/5 (No votes)
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 (http://phobos.iet.unipi.it/~pieri/EdT2/2181_Manual/Appendix_C.pdf[^]).

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

C++
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.

Target______Hex_______Output
0.9999_____0x7FFF____1.000000
0.5_________0x4000____0.500015
-0.5________0xC000____1.500046
-1.0________0x8000____1.000031

Any suggestions greatfully recieved, I'm a little out of my depth here!
Posted

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
 
Share this answer
 
Comments
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.
According to the documentation signed numbers are represented in the two's complement format. To convert them you may use this:
C++
// 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)); 
 
Share this answer
 
Comments
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)



CodeProject, 20 Bay Street, 11th Floor Toronto, Ontario, Canada M5J 2N8 +1 (416) 849-8900