it comes in as an unsigned long long int called "CAN_Incoming"
I would like to split this out into data packets, and to do that, I know that I need to split off chunks of bits from the front of the frame. For example, I know that the first 6 digits is one piece of data, so I need to break off "001110". The second piece might be the next 3, so "011".
What operator do I need to use to perform this function?
Bit shifting and masking (see operators posted by @anon57585045) should do the trick. Although you would need to check that your micro/ complier supports shifting of unsigned long long ints.
Assuming that the "001110" are the first 6 bits received and you get them into the unsigned long long int by shifting them in one at a time into the LSB, then your 6 bits are up at the top of of the uint64. Doing a << (aka shift left) will cause them to fall out of the top of the uint64. You need to do a >> (aka shift right) as @anon57585045 said.
Ok I've written a little code and have discovered that these frames are actually only half length (32 bits). So unsigned long int only.
My first data packet is "01111111000000001010000100000100"
The first two pieces of data I want to take out of this are "WiperState_M1" which is the first 3 bits, then "HW_Error_M1" which is the next 1 bit.
I have tried writing the following code to test out the basics but I just get 0 in the serial monitor...
M1_Status = 01111111000000001010000100000100;
int x = 31;
int y;
y = x - 3;
WiperState_M1 = (M1_Status >> y) & x;
Serial.println(WiperState_M1,BIN);
y = y - 1;
HW_Error_M1 = (M1_Status >> y) & x;;
The output I'm expecting in the serial monitor is on top vs what I'm getting is on the bottom:
3 / 1 / 1 / 1 / 1 / 1 / 0 / 0 / 20 / 0 / 1 / 1 / 0
3 / 1 / 1 / 1 / 1 / 1 / 0 / 0 / 0 / 0 / 1 / 0 / 0
This means that it seems to work great up to WiperPos_M1, which is a 10 bit variable. I'm currently using 0xA for a mask - is there some reason why that wouldn't work? There should be plenty of room for it in the int. It should be reading 20 but I'm getting 0.
As above, masks can be synthesized like this. Suppose you want to mask the lower 3 bits. The modulus is 8, 2^3. To make a mask, just subtract 1. 2^3-1 = 7. The mask for any modulus n that is a power of 2 (thus a series of consecutive bits) is 2^n - 1.
The significance is - in this way, shifts and masks can be based on the same defined constants, without having to puzzle them out and hard code them.
It is sometimes easier to work this kind of problems out on paper by aligning 1s and 0s. When you have the binary mask you want, any calculator with "programmer's" functionality will convert it to decimal or hex or octal to suit your tastes.
The meaningful names - that's the really important part. The technique in reply #9 wasn't fully explicated with a complete example. Let's try. Suppose I have an unsigned long, and I want to extract bit 9 to bit 13 inclusive. In this scenario, bit 14 might be the start of another bit field, or simply unused data. Often there are multiple fields so let's run with the former.
const int FIELD1_OFFSET = 9;
const int FIELD2_OFFSET = 14;
I need two numbers, the shift amount and the mask.
const int FIELD1_SIZE = FIELD2_OFFSET - FIELD1_OFFSET; // 5 in this case
const int FIELD1_MASK = (1 << FIELD1_SIZE) - 1 ; // 31 in this case
I think I'm ready!
unsigned long data = 0xDEADBEEF;
unsigned long result = ( data >> FIELD1_OFFSET ) & FIELD1_MASK;
Thanks everyone for your excellent input! I think I understand how it works now and have been able to get it to work correctly. Working with binary is definitely hard to get your head around, thanks so much for enlightening me!