2

I'm programming an arduino for led matrix project with shift registers i have to rotate output value (which is a byte) but when i use "<<" operator it does not rotate the value properly ,simply it adds zero to LSB .

byte ilk=0b01100001;
int latch=10;
int clock=8;
int data=9;
void setup(){
pinMode(latch,OUTPUT);
pinMode(data,OUTPUT);
pinMode(clock,OUTPUT);
}

void loop(){
  digitalWrite(latch,LOW);
  shiftOut(data,clock,MSBFIRST,ilk);
  digitalWrite(latch,HIGH);
  ilk=ilk<<1;
  delay(200);
}

How can i do this right way ?Is there any operator like ROL.

volki
  • 151
  • 4
  • 11
  • duplicate of http://stackoverflow.com/questions/776508/circular-shift-rotate-operations-in-c, which has a good answer. – Peter Cordes Aug 17 '15 at 17:21

3 Answers3

4

Because << is not the "rotate left" operator. It's the arithmetic left shift operator. You can use something like

uint32_t rotl(uint32_t n, uint32_n b)
{
    return (n << b) | (n >> (32 - b));
}

instead. Write sizeof(n) * CHAR_BIT - b in the right-hand side of the bitwise OR operator if you want this to be independent of the size of the integral type you use.

  • This has undefined behaviour when `b` == 0, because it involves a shift by >= the width of the type. See http://stackoverflow.com/questions/776508/circular-shift-rotate-operations-in-c for the current best-practice compiler-friendly C that will produce good ASM. – Peter Cordes Aug 17 '15 at 17:19
1

You could also code this like

uint16_t tmp = ilk << 1;
ilk = (uint8_t)tmp + *(((uint8_t *)(&tmp))+1);

The idea is that &tmp is a pointer to tmp as a word. Then the cast converts it to a byte pointer. Adding 1 to this pointer moves it up one byte. Dereferencing it delivers the high byte of tmp which is added to tmp. Then assigning the result to ilk takes the low byte of this operation. I did not double check but if the compiler is smart enough it can optimize this to "add the hi byte of tmp to tmp and take only the low byte of the result".

Or you could implement it as

ilk = ilk << 1 + (ilk >= (1 << sizeof(ilk));

In your case

ilk = ilk << 1 + (ilk >= 128);

Notice that both of my solutions do not require the compiler to optimize a shift of several bits.

Udo Klein
  • 6,784
  • 1
  • 36
  • 61
-1

Off the top of my head this should work, the overflow bits get discarded

byte temp = ilk & 1;
ilk <<= 1;
ilk |= (temp >> sizeof(temp));
user1646196
  • 589
  • 6
  • 28