how to cut off 3 bits from a 32bit integer

Hi!
I am reading a 32bit integer, but I only want 29bits out of it. the three first, most significant, are flags I dont want to use.

I tried & and | but I end up with weird results - maybe someone could give me an example how to cut of some bits?

I tried & and | but I end up with weird results

Post code, post results.

https://www.arduino.cc/en/pmwiki.php?n=Tutorial/BitMask

    CAN_config = canMsg.can_id;
    Serial.print("right from can: ");
    Serial.print(CAN_config);
    CAN_config << 3;
    Serial.print("  shifted 3 left: ");
    Serial.print(CAN_config);
    CAN_config >> 3;
    Serial.print("shifted three left: ");
    Serial.println(CAN_config);

    Serial.print("Message read: ");
    Serial.print(CAN_config);
    Serial.print(" = ");
    Serial.println(CAN_receive);

result:
CAN_config
right from can: 2147483665 shifted 3 left: 2147483665 shifted three left: 2147483665
Message read: 2147483665 = 17
CAN_config

void setup() {
  Serial.begin(9600);
  uint32_t y = 0xE1234567;
  Serial.println(y, HEX);
  y = y & 0x1fffffff;
  Serial.println(y, HEX);
}

void loop() {
}

As said, can_id holds more bits than needed for adress decode (from the library):

struct can_frame {
    uint32_t can_id;  /* 32 bit CAN_ID + EFF/RTR/ERR flags */
    uint8_t  can_dlc;
    uint8_t  data[8];
};
CAN_config << 3;

Oops

CAN_config <<= 3; The rest of the solution is left as an exercise for the reader.

   CAN_config << 3;

This line shifts but doesn’t assign it to anything.

Use:

   uint32_t masked_config = CAN_config & 0x1fffffff;

Now masked_config contains CAN_config without the flags.

ToddL1962:

void setup() {

Serial.begin(9600);
 uint32_t y = 0xE1234567;
 Serial.println(y, HEX);
 y = y & 0x1fffffff;
 Serial.println(y, HEX);
}

void loop() {
}

That one does not work, when It gives me FFFFFFF
FFFFFFF, when I enter with:

  uint32_t y = 0xfffffff;
    Serial.println(y, HEX);
    y = y & 0x1fffffff;
    Serial.println(y, HEX);

TheMemberFormerlyKnownAsAWOL:

CAN_config << 3;

Oops

CAN_config <<= 3;

The rest of the solution is left as an exercise for the reader.

Ohh noooooo. yes, that one solved it … so stupid I am :slight_smile:

That one does not work,

Count the 'f’s

when you mask

0xfffffff; // 7 f!

with

0x1fffffff;

it’s absolutely correct, that you end up with nothing more than

0xfffffff;

If I go back to your entry post, you wanted to cut off the MOST significant 3 bits. Than the left shift will give you a wrong result, because it will shift out 3 bits and add zeros on the LSB

void setup() {
  Serial.begin(115200);
  uint32_t in = 0xffffffff; //all 32 (!!!) bits set
  Serial.println(in, HEX);
  Serial.println(in, BIN);
  uint32_t outA = in & 0x1fffffff;
  Serial.println(outA, HEX);
  Serial.println(outA, BIN);
  in <<= 3;
  Serial.println(in, HEX);
  Serial.println(in, BIN);
}

void loop() {
}

FFFFFFFF
11111111111111111111111111111111
1FFFFFFF
11111111111111111111111111111
FFFFFFF8
11111111111111111111111111111000

imho masking is the correct way, if you want what you have asked for in your entry post.

AWOL was faster, but I’ll keep my post…

It's amazing how a simple masking problem generated so much discussion.

Well, no- the masking is wrong!
And the number of f is correct.

When I move 32 bits 3 positions to the left AND after that I move them 3 position s to the right I will erase the 3 most significant bits - meaning I will make them zero.
By this I ensure that the number left is encoded as a 29bit value- not as a 32bit value.

All the obscure bit mask magic everyone tries to apply will alter the bits in a unpredictable way- the first 3 bits can be zeros- they can be ones- I dont know- I just dont wont them.

My example with the F shows that when all bits are set to 1 (32 x 1) the result is not 29 x1 (and that it is when you just cut of the first 3msb) - so bit masking does not work to cut of 3 bits.

Please show us the code that you say doesn’t work.
Note that if you use signed types, the result may not be what you hope for.

All the obscure bit mask magic everyone tries to apply will alter the bits in a unpredictable way

There is nothing obscure about bit masking. “Everyone” is suggesting it because it’s extremely common and well understood. Perhaps you should take a breather and try to understand it. Then you would realize, it can’t possibly do what you say.

BetaCarotin:
Well, no- the masking is wrong!
And the number of f is correct.

My example with the F shows that when all bits are set to 1 (32 x 1) the result is not 29 x1 (and that it is when you just cut of the first 3msb) - so bit masking does not work to cut of 3 bits.

I have been doing bit masking for 35 years. I assure you it works. Here is the code you claim doesn't work:

 uint32_t y = 0xfffffff;
    Serial.println(y, HEX);
    y = y & 0x1fffffff;
    Serial.println(y, HEX);

You have 7 f's. If you mask with 0x1fffffff you get the same thing...0xfffffff.

And the desired result is 1fffffff !
So it does not work.
Why is that so hard to understand?

CAN identifiers are 29bit long, out of the CAN frame drops a 32bit value, containing flags at the beginning. These flags need to be cut off before processing the adress. Otherwise I will decode a flag as a part of an adress.

So how would you do bit masking= logical operations , that will set bits to zero- no matter what the other variable is- without altering all the other bits (29) you dont want to change? You dont! You just shift 3 left and three right, done.

So please try understand what I asked for.

BetaCarotin:
And the desired result is 1fffffff !
So it does not work.
Why is that so hard to understand?

It's YOU who FAILS TO UNDERSTAND!!!!
The masking suggested WORKS!!!
Here's another example code to demostrate it:

const uint32_t BIT_MASK_29Bits = 0x1fffffff;

void setup() {
  uint32_t val1 = 0x1abcdef2;
  uint32_t val2 = 0xff456789;

  Serial.begin(115200);

  Serial.print("val1 = 0x");
  Serial.print(val1, HEX);
  Serial.print(", applying mask 0x");
  Serial.println(val1 & BIT_MASK_29Bits, HEX);

  Serial.print("val2 = 0x");
  Serial.print(val2, HEX);
  Serial.print(", applying mask 0x");
  Serial.print(val2 & BIT_MASK_29Bits, HEX);

}

void loop() {
  // put your main code here, to run repeatedly:

}

and the result:

val1 = 0x1ABCDEF2, applying mask 0x1ABCDEF2
val2 = 0xFF456789, applying mask 0x1F456789

As you can see, in val2, the 3 most significant bits WERE MASKED

ToddL1962:
It's amazing how a simple masking problem generated so much discussion.

Naw, its just Covid.

-jimlee

Why is that so hard to understand?

we don't know why you struggle at that topic.
But you could put the posted codes in your Arduino and try to follow what we are saying.

CAN identifiers are 29bit long, out of the CAN frame drops a 32bit value, containing flags at the beginning. These flags need to be cut off before processing the adress. Otherwise I will decode a flag as a part of an adress.

so, mask the 32bit variable with

0b00011111111111111111111111111111

and you will see, that the first 3 bits are gone.