# C++ Circular Bit Shift with 2 variables

This topic is 2908 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

## Recommended Posts

So I'm programming a PIC microcontroller. It has 12 io pins and I need to control 10 of them. I have those 10 wired to LEDs in a circular pattern and I want a sort of stripe effect where it looks like the light is spinning. There are 2 different TRIS registers (A and C), each control individual pins. I want to shift a bit between 10 pins so I need a circular bit shift that works seamlessly with both variables. How do I do this in C++?
Example:
1:
trisa=000100
trisc=000000
||
\/

trisa=000010
trisc=000000

||
\/

trisa=000001
trisc=000000

||
\/

trisa=000000
trisc=001000

||
\/

trisa=000000
trisc=000100

||
\/

trisa=000000
trisc=000010

||
\/

trisa=000000
trisc=000001

||
\/

trisa=100000
trisc=000000

(pins 0 and 1 of trisc are used for other things.

##### Share on other sites
Hidden
void wrap_bits(uint32_t& a, uint32_t& b)
{
if (a & 1)
b |= 0x80000000;
}

// elsewhere
wrap_bits(trisa, trisc);
wrap_bits(trisc, trisa);

trisa >> 1;
trisc >> 1;

You need to use the bit shift operators << and >> along with & and | to combine and mask off bits. For example a rotate right of a 10-bit value would look something like: x = (x >> 1) | ((x & 1) << 10);

##### Share on other sites
So would I do this to mask the bits since they can only store 6 bits?

seq = (seq >> 1) | ((seq & 1) << 10);
trisa = seq << 4;
trisc = seq >> 2;

##### Share on other sites
Hidden
seq = (seq >> 1) | ((seq & 1) << 10);
trisa = seq << 4;
trisc = seq >> 2;

You're nobbling the bottom bits of trisc. Is this intentional? You mention they're used for a different purpose, but it's not clear if you wanted them included in this bit shifting malarky (e.g. if the LEDs are a countdown to some action controlled by the bottom two bits). Either way, you still want something more like:

[source lang="cpp"]seq = (seq >> 1) | ((seq & 1) << 10);
trisa = (seq & 0x3F0) >> 4; // 0x3F0 = 11 1111 0000b
trisc = (seq & 0xF) << 2 | (trisc & 0x3);[/source]

EDIT: Forgot to correct the thing I pointed out, d'oh.

I haven't programmed a PIC (16F877A if it matters) for over five years, so I may be completely wrong about these two problems:

Depending on your selected compiler/PIC, the maximum variable size could be 8 bits.
If that was the case, the above algorithms could fail.

Also, trisa and trisb are not directly used for output. They are called directional registers and control is a pin if used for input (1) or for output (0).
porta and portb are used to send output or read input from the pins.

##### Share on other sites
I realize that they are registers. Although the 8 bit thing will become a problem.

##### Share on other sites
// To initialize, set one register to 1 and other to 0 valueA = A & 0x3f; // value to rotate preserveA = A & 0xc0; // upper bits to preserve valueC = C & 0x3f; preserveC = C & 0xc0; // if using more than 8 bit registers, pad with 0xf (32 bits = 0xffffffc0) rightmostA = A & 0x01; // take value of rightmost bit rightmostC = C & 0x01; // if done before shifting, one could use valueA, valueC instead of A,C valueA >>= 1; // move the LEDs one position right valueC >>= 1; valueC |= (rightmostA << 5); // 000001 000000 will become 000000 100000 valueA |= (rightmostC << 5); // does not affect value unless we need to move between rows A = valueA | preserveA; C = valueC | preserveC;

The above looks right, should work with arbitrary CPU register size but operates on lower 6 bits only. Compacting the code is left as exercise for the reader.

Or maybe there is some other detail, in which case posting the PIC model and/or manual would be much more helpful.

##### Share on other sites
I don't know if you can use inline assembler with your PIC, if so, the rol and ror instrunctions can do just that, rotate bits left or right, and work exactly like the shift left-right instruction.

Something like:
 _asm { push ax // Save ax register mov al, trisa // Save trisa in al mov ah, trisc // Save trisc in ah rol al, 1 // rotate al bits by 1 on the left side rol ah, 1 // rotate ah bits by 1 on the left side mov trisa, al // Save al in trisa mov trisc, ah // Save ah in trisc pop ax // Restore ax register } 

That will work if trisa and trisc are 8 bits only, but i guess that's what you're using. If not, it's not hard to modify this code for 16 or 32 bits.

##### Share on other sites
Is there a reason you couldn't hardcode the required bitmasks in a lookup table and then cycle through them?

• ### Game Developer Survey

We are looking for qualified game developers to participate in a 10-minute online survey. Qualified participants will be offered a \$15 incentive for your time and insights. Click here to start!

• 16
• 11
• 24
• 43
• 75