tags:

views:

38

answers:

3

Hi guys,

I am using C to implement a packet stream that will be sent out via wireless and am stuck at the following problem. I have an unsigned int 2 bytes long, in the following format in binary: XXXX YYYY XXXX XXXX, where X & Y's are bits.

Looking at the format above, I need to just changed the YYYY bits and leave the other bits alone in the packet structure.

I have tried bit shifting and masking, but nothing seems to work.

I am not looking for just a solution so I can copy/paste. I want to learn the methods on how to get it to work and finally decided to post here.

Any help or guidance in the correct direction would be great.

Thanks!

A: 

value = (value & 0xF0FF) | (newY << 8); or a close variant thereof, depending on endianness?

Will A
Great!. Thank you. After posting this problem I tried it again and came up with the same logic, but your code was more simple and to the point (I had 4 lines to do what does in one line)
skybox
No problem at all, skybox - glad to be of assistance!
Will A
+5  A: 

Let's say you want to replace the YYYY bits with ZZZZ.

Firstly you need to clear the YYYY bits in the original value. This can be done with:

oldvalue & 0xF0FF

which gives you XXXX 0000 XXXX XXXX.

Next you need to take the new ZZZZ bits and shift them to the left, with:

z << 8

which gives 0000 ZZZZ 0000 0000.

Finally you need to combine the two values, using the or operator:

(oldvalue & 0xF0FF) | (z << 8)

which gives you XXXX ZZZZ XXXX XXXX.

Richard Fearn
+1 Short, sweet and very informative.
manneorama
Thank you for the explanation! Works great
skybox
You're welcome! :-)
Richard Fearn
A: 

Your description of the problem could do with some code, but I think you may be running into an endian problem. That could explain why your shifting and masking didn't do what you thought they would because you're actually working on the wrong byte.

The hton and ntoh family of functions switch to and from host and network endian-ness (big endian). Look up htons, ntohs, htonl, and ntohl for more info. These functions don't actually do anything if the host computer is big endian, but many (like x86) computers are little endian. On a little endian computer htons(0x1234) would result in 0x3412 because it swaps the bytes.

Since I don't know what your program flow looks like here's my best attempt at a clear example.

uint16_t set_those_bits(uint16_t x) {
    uint16_t mask = htons(0x0F00);
    return x | mask;
}

This function does not alter the endian-ness of the data passed in relative to the returned value, but it does assume that the value is network endian, so changes the endian-ness of the mask from host endian to network and then sets those bits in the result.

uint16_t clear_those_bits(uint16_t x) {
    uint16_t mask = htons(0xF0FF);
    return x & mask;
}

uint16_t toggle_those_bits(uint16_t x) {
    uint16_t mask = htons(0x0f00);
    return x ^ mask;
}
nategoose
Thanks! Lesson learned on little/big endian. New to the digital world. Will look more into your code and try to figure itout.
skybox