Log in

View Full Version : Manipulating bits


Robostang 548
29-12-2007, 23:09
Ok, I'm having a bit of trouble. I have been experimenting with using an off-board and so far everything has been going great. But now I'm having trouble fitting 10 gallons in an 8 gallon hat. My problem is that we have set up the serial link to send 8 bits at a time. Its perfect for sending joystick or pwm values back and forth but what happens when I want to send an integer that I have given an analog value? I know I can bit shift off the two right most bits and then replace them when they get to the coprocessor with zeros. That gives me the same value as when it was sent within 3. My question is, is there a way in c to take the two right-most bits of a value and put them into a byte and then fill up the rest of the byte with other right most bits of values so I don't wast space. I know how to cut this byte back up and distribute the bits to their corresponding values (my coprocessor runs on python) but I don't know how I would package and send something like this in C. Does anyone have a solution to this problem?

-Don

Salik Syed
29-12-2007, 23:18
Read up on the bitwise operators:
~ (NOT)
& (AND)
^ (XOR)
| (OR)

You can use these to manipulate bits pretty easily.

Robostang 548
29-12-2007, 23:22
OK, got it. There was a great example on wikipedia.
Thanks!

-Don

EricVanWyk
30-12-2007, 00:27
It looks like you are trying to "serialize" or "marshal" your data. Googling these terms may help.

In C, one nifty trick is to recast your data as strings.


int n=4;
char * s = (char *)&n;


Then, write a function that can push strings across.

Kevin Sevcik
30-12-2007, 01:02
One word of warning about the PIC, though it probably doesn't apply in your case if you're just using shifts for bit manipulation. Right shifts are unsigned only. So if you have a signed int that you want to divide by 4, x >> 2 only works if the value is positive. A negative value will have 0 shifted into the high order bits and will end up looking like a positive number.

dcbrown
04-01-2008, 12:23
144: var1 = var1 >> 2;
04524 0101 MOVLB 0x1
04526 90D8 BCF 0xfd8, 0, ACCESS ; set Carry flag to '0'
04528 33E7 RRCF 0xe7, F, BANKED ; C -> var1.hi -> C
0452A 33E6 RRCF 0xe6, F, BANKED ; C -> var1.lo -> C
0452C 90D8 BCF 0xfd8, 0, ACCESS ; set C flag to '0'
0452E 33E7 RRCF 0xe7, F, BANKED ; shift again
04530 33E6 RRCF 0xe6, F, BANKED


Its more accurate to say the compiler doesn't support signed shifts. The PIC is capable of doing signed shifts if asked to. All shifts are treated as unsigned by the compiler and have the carry in flag set to zero during the rotations. The PIC is capable of shifting in a '1' for negative values but the compile chooses not to -- 'cause all shifting operations are unsigned. Other compilers, such as HI-TECH's PIC C compiler chose to preserve the sign bit. This is a compiler specific implementation selection allowed by the ANSI C spec.

If you want to do signed shifts, you have to roll your own and change the instructions to:


BTFSC 0xe7, 7, BANKED
BRA NEGVALUE_SHIFT
POSVALUE_SHIFT:
BCF 0xfd8, 0, ACCESS ; Set CARRY (C) flag to '0'
RRCF 0xe7, F, BANKED ; C -> var1.hi -> C
RRCF 0xe6, F, BANKED ; C -> var1.lo -> C
BCF 0xfd8, 0, ACCESS ; clear C flag for next shift op
RRCF 0xe7, F, BANKED
RRCF 0xe6, F, BANKED
BRA DONE_SHIFT
NEGVALUE_SHIFT:
BSF 0xfd8, 0, ACCESS ; Set CARRY (C) flag to '1'
RRCF 0xe7, F, BANKED ; C -> var1.hi -> C
RRCF 0xe6, F, BANKED ; C -> var1.lo -> C
BSF 0xfd8, 0, ACCESS ; set C flag for next shift op
RRCF 0xe7, F, BANKED
RRCF 0xe6, F, BANKED
BRA DONE_SHIFT
DONE_SHIFT:


alternatively, in C a little more convoluted... plus there are other methods.


if (var1 > 0)
var1 = (var1 >> 2);
else
var1 = (varl >> 2) | 0xC000;