bitmath symbol << and digitalWrite

Hello
I was trying to use this library to hack an optical mouse with my arduino:

Can someone explain to me this type of code which is suppose to Write the address of the register we want to read:

pinMode (_sdioPin, OUTPUT);
for (; i>=0; i--)
{
digitalWrite (_sclkPin, LOW);
digitalWrite (_sdioPin, address & (1 << i));
digitalWrite (_sclkPin, HIGH);
}

this code is part of the file optimouse.cpp in the library

What I don't get in this code is that I thought digitalWrite could have only 1 or 0 as a second parameter.
From my understandign the symbol << mean a bit shift, so in this example if i = 2, 1<<2 = 100.
But how come this code can set a register?

Although the documentation suggests that digitalWrite() needs to take the values LOW or HIGH (0 or 1) as arguments, in fact any non-zero value will do for HIGH. I haven't looked at the source code for this function, but it will be faster to implement
"if value isn't zero then make the pin high, else make it low"
rather than
"If value is one, make the pin high, if it's zero, make it low, otherwise what should I do??"

digitalWrite() writes the pin low if the second argument is a 0 (ie, evaluates to false), otherwise it writes the pin high. This is pretty normal behavior - if you pass an integer datatype where a boolean is expected, you expect it to be false if 0, true if not zero.

What that does is loop (presumably 8 times) through that code. each pass through the loop, i has changed, so a different bit of "address" is used to determine whether the pin is written high or low. The practice of a bitwise and with a "bit mask" as is done there is a very common trick to use in embedded programming.

It's a bitbang'ed implementation of some serial protocol.

Also, << is bitwise, so 1<<2 is 0b00000100, decimal value 4. "100" would not be considered a correct way to write that.

Oki thanks a lot ! :slight_smile:
it's a bit more clearer.

So just to be sure I understood well.
let's say I want to read the register 0x03 of an SPI component
As soon as I set up the pin DATA to output, that put the SPI component in a kind of "listenning" mode. And each time we set the pin Data to high it write a value to set the register we want to read.
Then to read the register 0x03 we set to high the bit i=0 and i=1.
And then only after we switch the data pin to input to end the process of writing.

Am I right?

sephir29:
Oki thanks a lot ! :slight_smile:
it's a bit more clearer.

So just to be sure I understood well.
let's say I want to read the register 0x03 of an SPI component
As soon as I set up the pin DATA to output, that put the SPI component in a kind of "listenning" mode. And each time we set the pin Data to high it write a value to set the register we want to read.
Then to read the register 0x03 we set to high the bit i=0 and i=1.
And then only after we switch the data pin to input to end the process of writing.

Am I right?

I think not, if I understand your question. Because SPI uses separate pins for input and output, MISO and MOSI.

Hi Thanks again for your answer.
I'm amazed about how fast people reply in this community :slight_smile:

I'm using this component: ADNS2610
So it's maybe not an SPI component, sorry I'm really newb on this topic :slight_smile:
here's the datasheet of the component:

And I also attached a picture of it.

Based on that can you explain once again how this code can write the adress of a register we want to read?:slight_smile:
pinMode (_sdioPin, OUTPUT);
for (; i>=0; i--)
{
digitalWrite (_sclkPin, LOW);
digitalWrite (_sdioPin, address & (1 << i));
digitalWrite (_sclkPin, HIGH);
}

the register adress is 0x03
so is it because we set up the pin sdioPin (Data) to output before calling digitalWrite that the component knows he has to listen the bit for the register we want to read??

Thanks in advance :slight_smile:

sephir29:
so is it because we set up the pin sdioPin (Data) to output before calling digitalWrite that the component knows he has to listen the bit for the register we want to read??

No, it's just because the component remains in a listening state between transactions. See page 13 of the datasheet.

Yeah, you're bitbanging a 2-wire serial protocol that looks strikingly similar to I2C only without the part addressing...

Take a look at figure 21 - that shows how you tell it to read a register; you're manipulating SDCLK and SDIO while sending the address, then manipulating SDCLK and letting the part drive SDIO while reading the value out. Like I2C, the high bit of the address (in this case the register address, instead of the device address like the first byte of I2C transaction) tells the part whether it's a read or write operation. There's also an example of writing 1 page earlier (fig 19)