View previous topic :: View next topic |
Author |
Message |
Guest
|
2's Complement Bit toggle |
Posted: Sat Mar 07, 2009 4:33 pm |
|
|
Hello,
I have a negative 16bit number. I need to perform 2's complement to get the absolute value. I was looking in the manual and found the bit_test() function. with this I can test the msb. IF it returns a 1 the number will be negative and twos complement performed. But does CCS have a bit toggle instruction like in Assembly language? Or do I need to use if else statements and go down and toggle every bit? Thank you for you help |
|
![](templates/subSilver/images/spacer.gif) |
Sydney
Joined: 13 Feb 2009 Posts: 71
|
|
Posted: Sat Mar 07, 2009 4:41 pm |
|
|
You could test the number and do value = -value, or use the abs() function. |
|
![](templates/subSilver/images/spacer.gif) |
Guest
|
|
Posted: Sat Mar 07, 2009 4:53 pm |
|
|
So if im understanding correctly value=-value or using the abs() function is the same as doing the 2's complement?
More info on data:
Value = 1011 1111 1111 1111
The 10xx xxxx xxxx xxxx represents diffrernt flags for data.
the xx11 xxxx xxxx xxxx represents negative data. So then twos complment needs to be performed on the remaining 12 bits.
So if I take the ab() of the whole 16 bit it would yield invalid results. |
|
![](templates/subSilver/images/spacer.gif) |
FvM
Joined: 27 Aug 2008 Posts: 2337 Location: Germany
|
|
Posted: Sat Mar 07, 2009 5:10 pm |
|
|
Sorry, it's completely unclear what you want to say here. |
|
![](templates/subSilver/images/spacer.gif) |
Guest
|
|
Posted: Sat Mar 07, 2009 5:21 pm |
|
|
ok I will try to clear things up!
Below 'value' represents -1. I want to test bit 13 and bit 12 to see if it is 1. If it is 1 it means the number is negative and twos complement needs to be performed to get the absolute value. Sydney suggested using value =-value or the abs() function. But I was saying this I don't think would work because bits 15 and 14 represent new data and alarm flags. This data is coming from an accelerometer. So I am trying to figure out how to take the twos complement of the remaining 12 bit number. I hope this clear things up.
Value = 1011 1111 1111 1111
The 10xx xxxx xxxx xxxx represents different flags for data(from accelerometer.
the xx11 xxxx xxxx xxxx represents negative data. So then twos complement needs to be performed on the remaining 12 bits. |
|
![](templates/subSilver/images/spacer.gif) |
Sydney
Joined: 13 Feb 2009 Posts: 71
|
|
Posted: Sun Mar 08, 2009 2:28 am |
|
|
Sorry I misunderstood you would use exclusive or to invert the 12 bits.
Code: | value ^= 0b0000111111111111;
++value; |
Last edited by Sydney on Sun Mar 08, 2009 3:13 am; edited 1 time in total |
|
![](templates/subSilver/images/spacer.gif) |
Sydney
Joined: 13 Feb 2009 Posts: 71
|
|
Posted: Sun Mar 08, 2009 3:12 am |
|
|
Be aware the most negative number will return the same value, because the range is -2048 to 2047 |
|
![](templates/subSilver/images/spacer.gif) |
Ttelmah Guest
|
|
Posted: Sun Mar 08, 2009 4:09 am |
|
|
Realistically, if you are going to use the number for anything else, the 'best' solution, is probably to just mask out the extra bits.
So:
Code: |
int16 val_from_unit;
signed int16 numeric_val;
numeric_val=val_from_unit & 0x07FF; //get the eleven numeric bits
if (val_from_unit & 0x0800) numeric_val=-numeric_val; //sign extend
|
numeric val, then contains a normal signed int16, wich will work with the standard arithmetic functions. Makes conversion, and testing a lot easier.
Best Wishes |
|
![](templates/subSilver/images/spacer.gif) |
FvM
Joined: 27 Aug 2008 Posts: 2337 Location: Germany
|
|
Posted: Sun Mar 08, 2009 4:19 am |
|
|
Quote: | Below 'value' represents -1 | No, it doesnt. -1 is represented by all bits set to one. Or are you going to define you're own number format? |
|
![](templates/subSilver/images/spacer.gif) |
Ttelmah Guest
|
|
Posted: Sun Mar 08, 2009 9:07 am |
|
|
You'd just need to use :
Code: |
numeric_val=val_from_unit & 0x07FF; //get the eleven numeric bits
if (val_from_unit & 0xF800) numeric_val=-numeric_val; //sign extend
|
Not exactly 'rocket science'.
And in fact, I do use different custom numeric formats a lot.
Best Wishes |
|
![](templates/subSilver/images/spacer.gif) |
Guest
|
|
Posted: Sun Mar 08, 2009 10:30 am |
|
|
First of all thanks for everyones input!
Value = 1011 1111 1111 1111
Value does represent -1 one in this case. Bit 15 and 14 represent data flags and the remaining represents the actual number.
Please check out the following address. look at page 14. This should clear up what I am trying to do....read in acceleration values. I am using the ADIS16350.
Please go to analog devices website and look at the data sheet. It will not let me post the link in the post. |
|
![](templates/subSilver/images/spacer.gif) |
Ttelmah Guest
|
|
Posted: Sun Mar 08, 2009 10:55 am |
|
|
OK. 14bit, not 12bit.
Use:
Code: |
int16 val_from_unit;
signed int16 numeric_val;
numeric_val=val_from_unit & 0x1FFF; //get the thirteen numeric bits
if (val_from_unit & 0x2000) numeric_val |= 0xE000; //sign extend
|
This should give you the numeric value from the unit, as a signed value, in the 'numeric_val' variable, if given the 16bit value read in 'val_from_unit'.
Best Wishes |
|
![](templates/subSilver/images/spacer.gif) |
Sydney
Joined: 13 Feb 2009 Posts: 71
|
|
Posted: Sun Mar 08, 2009 10:57 am |
|
|
Surely all you need to do is mask the 2 msbs and put the result into a signed int16, giving you -8192 to 8191 for the 14-bit measurements, since you obviously need to know whether the measurement is positive or negative, and the best way to do that would be to leave it negative. |
|
![](templates/subSilver/images/spacer.gif) |
Ttelmah Guest
|
|
Posted: Sun Mar 08, 2009 11:08 am |
|
|
Wont give you a negative result _ever_.
Think of it this way. Take the example in the data sheet, of -1g, read as -397. This is returned as 0x3E73, after you mask off the top two bits. 15987 if put into a signed integer.
The sign bit (top bit of the 16 bit vaue), is not set...
You either have to test if the value is greater than 8192, and if so, subtract 16384, or just test bit 13, and if it is set (implying the result is negative), set the top three bits. This is what I have posted. The latter is quicker than the comparison test. This would turn the above value, into: 0xFE73, which stored as a signed integer, is the right value to give -397 as required.
So the alternative, would be:
Code: |
int16 val_from_unit;
signed int16 numeric_val;
numeric_val=val_from_unit & 0x3FFF; //get the fourteen bits with sign
if (numeric_val>8192) numeric_val -= 16384; //sign extend
|
The version I have already posted, is faster.
Best Wishes |
|
![](templates/subSilver/images/spacer.gif) |
FvM
Joined: 27 Aug 2008 Posts: 2337 Location: Germany
|
|
Posted: Sun Mar 08, 2009 1:35 pm |
|
|
I had some difficulties to understand what you're trying to achieve, due to the way, the question was asked.
If a numeric value is embedded in an assembled data word, I would mask out the numeric value and process it using a standard numeric format, int16 in this case. Ttelmah altready has suggested this. That's the, purpose of using a high level language, not to care for bit level processing with numeric standard operations. Details in execution speed most likely don't matter with measurement values read out with kHz or below sample rate.
I think that extraction of the numeric fields is also the method, that has been obviously imagined by the authors of the Analog data sheet.
Last edited by FvM on Sun Mar 08, 2009 1:40 pm; edited 1 time in total |
|
![](templates/subSilver/images/spacer.gif) |
|