tags:

views:

565

answers:

10

Hi All, I am working on a little Hardware interface project based on the Velleman k8055 board.

The example code comes in VB.Net and I'm rewriting this into C#, mostly to have a chance to step through the code and make sense of it all.

One thing has me baffled though:

At one stage they read all digital inputs and then set a checkbox based on the answer to the read digital inputs (which come back in an Integer) and then they AND this with a number:

i = ReadAllDigital
cbi(1).Checked = (i And 1)
cbi(2).Checked = (i And 2) \ 2
cbi(3).Checked = (i And 4) \ 4
cbi(4).Checked = (i And 8) \ 8
cbi(5).Checked = (i And 16) \ 16

I have not done Digital systems in a while and I understand what they are trying to do but what effect would it have to AND two numbers? Doesn't everything above 0 equate to true?

How would you translate this to C#?

+16  A: 

This is doing a bitwise AND, not a logical AND.

Each of those basically determines whether a single bit in i is set, for instance:

5 AND 4 = 4
5 AND 2 = 0
5 AND 1 = 1

(Because 5 = binary 101, and 4, 2 and 1 are the decimal values of binary 100, 010 and 001 respectively.)

Jon Skeet
5 AND 4 = 4, of course, that's why the question said (5 AND 4) \ 4
MSalters
Doh, fixed thanks :)
Jon Skeet
A: 

Think of this in binary e.g.

10101010

AND

00000010

yields 00000010

i.e. not zero. Now if the first value was

10101000

you'd get

00000000

i.e. zero.

Note the further division to reduce everything to 1 or 0.

Brian Agnew
+13  A: 

I think you 'll have to translate it to this:

i & 1 == 1

i & 2 == 2

i & 4 == 4

etc... This is using the bitwise AND operator.

When you use the bitwise AND operator, this operator will compare the binary representation of the two given values, and return a binary value where only those bits are set, that are also set in the two operands.

For instance, when you do this:

2 & 2

It will do this:

0010 & 0010

And this will result in:

 0010
 0010
&----
 0010

Then if you compare this result with 2 (0010), it will ofcourse return true.

Frederik Gheysels
A: 

(i and 16) / 16 extracts the value (1 or 0) of the 5th bit.

1xxxx and 16 = 16 / 16 = 1
0xxxx and 16 = 0 / 16 = 0
Dario Solera
+1  A: 

And operator performs "...bitwise conjunction on two numeric expressions", which maps to '|' in C#. The '\ is an [integer division][2], and equivalent in C# is /`, provided that both operands are integer types.

Anton Gogolev
+1  A: 

The constant numbers are masks (think of them in binary). So what the code does is apply the bitwise AND operator on the byte and the mask and divide by the number, in order to get the bit.

For example:

xxxxxxxx & 00000100 = 00000x000
if x == 1
    00000x00 / 00000100 = 000000001
else if x == 0
    00000x00 / 00000100 = 000000000
alkar
+1  A: 

As said this is a bitwise AND, not a logical AND. I do see that this has been said quite a few times before me, but IMO the explanations are not so easy to understand.

I like to think of it like this:

Write up the binary numbers under each other (here I'm doing 5 and 1):

101
001

Now we need to turn this into a binary number, where all the 1's from the 1st number, that is also in the second one gets transfered, that is - in this case:

001

In this case we see it gives the same number as the 2nd number, in which this operation (in VB) returns true. Let's look at the other examples (using 5 as i):

(5 and 2)

101
010
----
000

(false)

(5 and 4)

101
100
---
100

(true)

(5 and 8)

0101
1000
----
0000

(false)

(5 and 16)

00101
10000
-----
00000

(false)

EDIT: and obviously I miss the entire point of the question - here's the translation to C#:

cbi[1].Checked = i & 1 == 1;
cbi[2].Checked = i & 2 == 2;
cbi[3].Checked = i & 4 == 4;
cbi[4].Checked = i & 8 == 8;
cbi[5].Checked = i & 16 == 16;
kastermester
+3  A: 

Just to add: It's called bitmasking http://en.wikipedia.org/wiki/Mask_(computing)

A boolean only require 1 bit. In the implementation most programming language, a boolean takes more than a single bit. In PC this won't be a big waste, but embedded system usually have very limited memory space, so the waste is really significant. To save space, the booleans are packed together, this way a boolean variable only takes up 1 bit.

You can think of it as doing something like an array indexing operation, with a byte (= 8 bits) becoming like an array of 8 boolean variables, so maybe that's your answer: use an array of booleans.

RichN
+1  A: 

In C# use the BitArray class to directly index individual bits.

To set an individual bit i is straightforward:

b |= 1 << i;

To reset an individual bit i is a little more awkward:

b &= ~(1 << i);

Be aware that both the bitwise operators and the shift operators tend to promote everything to int which may unexpectedly require casting.

Peter Wone
A: 

I prefer to use hexadecimal notation when bit twiddling (e.g. 0x10 instead of 16). It makes more sense as you increase your bit depths as 0x20000 is better than 131072.

Jason Morse