Sign up ×
Arduino Stack Exchange is a question and answer site for developers of open-source hardware and software that is compatible with Arduino. It's 100% free, no registration required.

I were examining shiftOut() function code in wiring_shift.c and I didn't quite understand what is going in digitalWrite function. I see !!(val & (1 << i)) is taking the bit value from val but how exactly it works?

The whole function is below.

void shiftOut(uint8_t dataPin, uint8_t clockPin, uint8_t bitOrder, uint8_t val)
{
    uint8_t i;

    for (i = 0; i < 8; i++)  {
        if (bitOrder == LSBFIRST)
            digitalWrite(dataPin, !!(val & (1 << i)));
        else    
            digitalWrite(dataPin, !!(val & (1 << (7 - i))));

        digitalWrite(clockPin, HIGH);
        digitalWrite(clockPin, LOW);        
    }
}
share|improve this question
    
!!(val & (1 << i)) is the most complex part of this code. If you do understand this, then what is the part you do not understand? –  Edgar Bonet Jun 1 at 8:56
    
@edgar-bonet Actually this was the question. I can see it somehow calculates the bit value, but I didn't understand how it do this. –  wizofwor Jun 1 at 9:01
    
You do understand the behaviour of the shiftOut function? I mean, you do understand that it'll shift out a value (in binary form). And will give a clock pulse along with it. –  FuaZe Jun 1 at 10:29

1 Answer 1

up vote 4 down vote accepted

I'll assume bitOrder == LSBFIRST.

  • i is the bit number, i.e. the “index” of the next bit to write
  • 1 is 00000001 in binary
  • << is the shift left operator. It returns its first argument shifted left by as many positions as indicated by the second argument
  • 1<<i is binary 00000001 shifted left by i positions, i.e. something like 0...010...0, where the single 1 is in the i-th position counting from the right (rightmost being position 0)
  • & is the “bitwise and operator”, where any_bit & 0 is zero and any_bit & 1 is any_bit
  • val & (1 << i) is 0...0(i-th bit of val)0...0 in binary, where the i-th bit of val is in the i-th position of the result
  • !! is a double negation: it converts zero to zero and any non-zero value to one
  • !!(val & (1 << i)) is either 0 or 1, and is exactly the i-th bit of val
share|improve this answer
    
let me summarize what I understand. Let assume val = '10010111'; for i=2 !!(val & (1 << i)) = !!('10010111' & '00000100') = !!('00000100') = 1 If i is = 3 !!(val & (1 << i)) = !!('10010111' & '00001000') = !!('00000000') = 0 –  wizofwor Jun 1 at 10:43
    
This is correct! –  Edgar Bonet Jun 1 at 10:48
    
And this means if I give 16bit or longer data to shiftOut, it will send least significant 8 bits and ignore the rest. –  wizofwor Jun 1 at 10:52
1  
shiftOut() takes uint8_t data. If you call it with a 16-bit argument, the compiler will implicitly remove the 8 most significant bits before the actual call to shiftOut(). –  Edgar Bonet Jun 1 at 11:01

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.