Jump to content
  • Advertisement
Sign in to follow this  
MadScientist

C++ Circular Bit Shift with 2 variables

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

If you intended to correct an error in the post then please contact us.

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 this post


Link to post
Share on other sites
Advertisement
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;

Share this post


Link to post
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 this post


Link to post
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.

Share this post


Link to post
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 this post


Link to post
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 this post


Link to post
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 this post


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

Share this post


Link to post
Share on other sites
Sign in to follow this  

  • Advertisement
×

Important Information

By using GameDev.net, you agree to our community Guidelines, Terms of Use, and Privacy Policy.

GameDev.net is your game development community. Create an account for your GameDev Portfolio and participate in the largest developer community in the games industry.

Sign me up!