Create an account

Very important

  • To access the important data of the forums, you must be active in each forum and especially in the leaks and database leaks section, send data and after sending the data and activity, data and important content will be opened and visible for you.
  • You will only see chat messages from people who are at or below your level.
  • More than 500,000 database leaks and millions of account leaks are waiting for you, so access and view with more activity.
  • Many important data are inactive and inaccessible for you, so open them with activity. (This will be done automatically)


Thread Rating:
  • 527 Vote(s) - 3.43 Average
  • 1
  • 2
  • 3
  • 4
  • 5
Manually cast signed char

#1
I'm working with some embedded hardware, a Rabbit SBC, which uses Dynamic C 9.

I'm using the microcontroller to read information from a digital compass sensor using one of its serial ports.

The sensor sends values to the microcontroller using a single signed byte. (-85 to 85)

When I receive this data, I am putting it into a `char` variable

This works fine for positive values, but when the sensor starts to send negative values, the reading jumps to 255, then works its way back down to 0. I presume this is because the last bit is being used to determine the negative/positive, and is skewing the real values.

My inital thought was to change my data type to a `signed char`.

However, the problem I have is that the version of Dynamic C on the Microcontroller I am using does not natively support signed char values, only unsigned.

I am wondering if there is a way to manually cast the data I receive into a signed value?
Reply

#2
I think this is what you're after (assumes a 32-bit int and an 8-bit char):

unsigned char c = 255;
int i = ((int)(((unsigned int)c) << 24)) >> 24;

of course I'm assuming here that your platform does support signed integers, which may not be the case.
Reply

#3
Signed and unsigned values are all just a bunch of bits, it is YOUR interpretation that makes them signed or unsigned. For example, if your hardware produces 2's complement, if you read 0xff, you can either interpret it as -1 or 255 but they are really the same number.

Now if you have only `unsigned char` at your disposal, you have to emulate the behavior of negative values with it.

For example:

c < 0

changes to

c > 127

Luckily, addition doesn't need change. Also subtraction is the same (check this I'm not 100% sure).

For multiplication for example, you need to check it yourself. First, in 2's complement, here's how you get the positive value of the number:

pos_c = ~neg_c+1

which is mathematically speaking `256-neg_c` which congruent modulo 256 is simply `-neg_c`

Now let's say you want to multiply two numbers that are unsigned, but you want to interpret them as signed.

unsigned char abs_a = a, abs_b = b;
char final_sign = 0; // 0 for positive, 1 for negative
if (a > 128)
{
abs_a = ~a+1
final_sign = 1-final_sign;
}
if (b > 128)
{
abs_b = ~b+1
final_sign = 1-final_sign;
}
result = abs_a*abs_b;
if (sign == 1)
result = ~result+1;

You get the idea!
Reply

#4
If your platform supports `signed int`s, check out some of the other answers.

If not, and the value is definitely between -85 and +85, and it is two's complement, add 85 to the input value and work out your program logic to interpret values between 0 and 170 so you don't have to mess with signed integers anymore.

If it's one's complement, try this:

if (x >= 128) {
x = 85 - (x ^ 0xff);
} else {
x = x + 85;
}

That will leave you with a value between 0 and 170 as well.

EDIT: Yes, there is also sign-magnitude. Then use the same code here but change the second line to `x = 85 - (x & 0x7f)`.
Reply

#5
You just need to pull out your reference book and read how negative numbers are represented by your controller. The rest is just typing.

For example, two's complement is represented by taking the value mod 256, so you just need to adjust by the modulus.

int signed_from_unsignedchar(unsigned char c)
{
int result = c;
if (result >= 128) result -= 256;
return result;
}

[One's complement][1] is much simpler: You just flip the bits.

int signed_from_unsignedchar(unsigned char c)
{
int result = c;
if (result >= 128) result = -(int)(unsigned char)~c;
return result;
}

Sign-magnitude represents negative numbers by setting the high bit, so you just need to clear the bit and negate:

int signed_from_unsignedchar(unsigned char c)
{
int result = c;
if (result >= 128) result = -(result & 0x7F);
return result;
}


[1]:

[To see links please register here]

Reply



Forum Jump:


Users browsing this thread:
1 Guest(s)

©0Day  2016 - 2023 | All Rights Reserved.  Made with    for the community. Connected through