How to shift more than one bit (but not all bits)

Hello!

I want to manipulate the port register, PORTH to be precise, on my arduino mega 2560 using a bit pattern.

Unfortunately port H2, which would be represented by the third lowest bit, is not available on the mega2560.

Therefore I have to manipulate my bit pattern by shifting the upper 6 bits to the left (one position) and leave the lowest two bits untouched.

Example:

0b00111111 must become 0b01111011

or

0b00100101 must become 0b01001001

...but I have no idea how to do that using bit wise operators...

Any ideas, anyone?

You could store the lowest two bits in a variable, write to their positions zeros, shift the whole to the left and then insert the last to bits of the variable.

byte a = 0b001111^11; // ^ is just the marker where the zero has to be inserted!
byte b = a;
b = (b << 6) >> 6; // To remove the 6 bits in front. Value of b: 0b00000011;
a = (a >> 2) << 2; // To remove the last two bits. Value of a: 0b00111100;
a = a << 1; //Shift the whole thing one to the left. Value of a: 0b01111000;
a = a | b; // insert the last two bits again. Value of a: 0b01111011;

This might not be the fastest way, so could use other bit operations instead to improve performance. I'll post an other option later on.

n = (((n & 0b01111100) << 1) | (n & 0b00000011))

Here another option:

byte a = 0b001111^11; // ^ is just the marker where the zero has to be inserted!
byte b = a;
b = b & 0b00000011; // To remove the 6 bits in front. Value of b: 0b00000011;
//or b = b & 3;
a = a & 0b11111100; // To remove the last two bits. Value of a: 0b00111100;
// or a = a & 252;
a = a << 1; //Shift the whole thing one to the left. Value of a: 0b01111000;
a = a | b; // insert the last two bits again. Value of a: 0b01111011;

Therefore I have to manipulate my bit pattern by shifting the upper 6 bits to the left (one position) and leave the lowest two bits untouched.

No you should use the bitwise AND and OR operations:-

out =  (pattern << 1) & 0xF8 | (pattern & 0x03) ;

This leaves a zero in bit 2

The easiest way I can think of would be to mask out the lower 2 bits of your original to another variable, do your shift and then AND your copy back in. So...

a = 0B00111111;
b = a & 0b00000011;
c = a << 1;
portH = a | b;

Of course in this example, pin PH2 would end up with a 1 in it. Does that matter?

I'm sure there is a much more elegant solution.

Wow... 4 responses while I was typing mine. lol

And we have more elegant solutions!

0b00111111 must become 0b01111011

0b01111011 = (((0b00111111 & 0b01111100) << 1) | (0b00111111 & 0b00000011))
0b01111011 = (((0b00111100) << 1) | (0b00000011))
0b01111011 = (((0b01111000)) | (0b00000011))
0b01111011 = (0b01111011)

This brings up something I have been searching for and haven't found. Does there exist a program that allows you to test bitwise operations but with an interface just like writing C code? Being able to experiment with something like that would definitely help people to learn how it works and get better at it.

Hmm... maybe I should write one. Bet I would be darn good at it by the time I finish! lol

A bonus feature would be for you to give it a problem (like this one) and have it figure out the most efficient way to solve it in code.

No sense in re-inventing the wheel. Anyone know of something like this that already exists?

An HP48g calculator can be made to do it but it's just easier to figure with a simple text editor as in my last post.

which would be represented by the third lowest bit, is not available on the mega2560.

Therefore I have to manipulate my bit pattern by shifting the upper 6 bits to the left (one position) and leave the lowest two bits untouched.

The highlighted parts don't "match." Are you dealing with the upper 6 bits or upper 5 bits?

Since H2 is not connected to anything, you can set it however you want, and nothing will ever know.
Since H0:1 are overridden by Serial2, I think you can set them however you want, too, and the values won't get to the actual pins. (IF you're using Serial2.)