September 16th, 2013, 02:23 AM

Please help to explain how this C programming works
any kind soul can explain detailly how below programing works?
uint16_t read_blk;
NANDcmd[3] = 0;
NANDcmd[4] = 0;
NANDcmd[5] = 0;
for (read_blk=0; read_blk<4100; read_blk++)
{ NANDcmd[3] = (uint8_t)((read_blk<<7) & 0x80);
NANDcmd[4] = (uint8_t)((read_blk>>1) & 0xFF);
NANDcmd[5] = (uint8_t)((read_blk>>9) & 0x0F);
}
September 16th, 2013, 09:22 AM

What don't you understand?
<< is the left shift operator. <<7 shifts read_blk left seven times.
>> is the right shift operator. It shifts the operand to the right the number of times indicated.
& is the AND operator which ANDs the two operands.
0xFF is hexadecimal representation of 255.
uint8_t is a datatype definition for an unsigned 8bit integer, which is commonly called a "byte".
September 17th, 2013, 12:25 AM

Originally Posted by dwise1_aol
What don't you understand?
<< is the left shift operator. <<7 shifts read_blk left seven times.
>> is the right shift operator. It shifts the operand to the right the number of times indicated.
& is the AND operator which ANDs the two operands.
0xFF is hexadecimal representation of 255.
uint8_t is a datatype definition for an unsigned 8bit integer, which is commonly called a "byte".
i would like to know the how is the work flows. for examle if read_blk=2, can any 1 let know know the process line by line?
September 17th, 2013, 12:32 AM

So walk through the code. It's all right there.
What is it that you do not understand? Please answer that question so that we can help you.
Is it that you do not understand bitwise operations? What shifting means? What ANDing means? What hexadecimal is? Do you understand how to convert from hexadecimal to binary in order to get the bit pattern?
Obviously, if you do not understand all those topics, then you would not be able to understand a normal explanation. Equally obviously is that if you do understand those necessary topic then you wouldn't have to ask what that code does.
What do you not understand?
What is the bit pattern of 2?
What bit pattern do you get from 2<<7, which is shifting 2 to the left seven times?
What bit pattern do you get when you AND that with 0x80?
BTW, when you cast a 16bit integer to being an 8bit integer, then you simply throw away the higherorder 8 bits and you keep the lowerorder 8 bits.
When you assign a new value to a variable, what happens to the old value? It's gone. So after that forloop is finished, NANDcmd will contain the results of read_blk having been 4099. So then what is the bit pattern of 4099?
That's how you work through it. Now what part do you not understand?
Last edited by dwise1_aol; September 17th, 2013 at 12:45 AM.
September 17th, 2013, 05:04 PM

OK, so you don't know anything, which is what I needed for you to establish for us. That means we have to explain everything to you. Otherwise, you wouldn't understand our explanation anyway.
We humans use the decimal system for numbers, because we have ten digits (AKA "fingers") to count with and so each decimal digit can have one of ten values ranging from 0 to 9. Digital computers don't use the decimal system, because they don't have any fingers to count with but rather two logic levels represented by two distinct voltages. Therefore, computers' numbers are in binary, AKA "Base 2", because each binary digit (AKA "bit") in a computer's number can have one of only two values, 0 and 1.
For the following, I will use FORTRAN notation for exponentiation, which is the double asterix, such that 10**3 means "ten raised to the third power". I am using this notation instead of using the caret (^), which may be popular but it's also confusing for C novices because in C the caret is the bitwise exclusiveOR operator (XOR), such that 10^3 does not raise 10 to the third power, which would yield 1000, but rather XORs 10 and 3 to yield 9  obviously, 1000 and 9 are not the same value.
However, one thing that decimal and binary numbers have in common is that they are placevalue numbers, meaning that the position of the digit within its number gives it value. The position values start with 1 and increase by powers of the base as you go to the left. So going from right to left in a decimal (ie, base 10) number the position values are 1's (10**0), 10's (10**1), 100's (10**2), 1000's (10**3), etc. Similarly, going from right to left in a binary (ie, base 2) number the position values are 1's (2**0), 2's (2**1), 4's (2**2), 8's (2**3), 16's (2**4), 32's (2**5), 64's (2**6), 128's (2**7), etc  programmers quickly become very familiar with the powers of 2.
One thing this allows us to do is to convert a decimal number to the binary number of the same value and vice versa. So for a decimal 2 you would set the 2's digit to 1 and the rest to zero, so the 8bit binary bit pattern for 2 would be 00000010B (the trailing "B" is an assembly language convention to indicate a binary value). Similarly, a 5 would have the 4's and the 1's bits set to 1: 00000101B. There is a manual procedure of converting from decimal to any other number base which involves successively dividing the decimal number by the target base and writing the remainders down as the digits, but an easier way is to use Windows' calc program in the scientific view (for WinXP) or the programmer's view (for Win7).
However, there is no binary notation in C, but rather only decimal, octal (base 8) and hexadecimal (base 16). The reason for octal and hexadecimal is that if you take the binary bit pattern and group the bits three at a time you can represent those three bit with an octal digit, and if you group them four at a time you can represent them with a hex digit. Long binary numbers can get very tedious to write and to read, so converting them to hexadecimal makes it much easier. You can convert between binary and hex on sight:
Code:
Dec Bin Hex  Dec Bin Hex  Dec Bin Hex  Dec Bin Hex
0 0000 0  4 0100 4  8 1000 8  12 1100 C
1 0001 1  5 0101 5  9 1001 9  13 1101 D
2 0010 2  6 0110 6  10 1010 A  14 1110 E
3 0011 3  7 0111 7  11 1011 B  15 1111 F
In C, a hexadecimal value is prefaced with "0x", so 0x80 is 80 hex. From the table, you can see that the bit pattern for 0x80 is 10000000B. Similarly, from the code you posted, you can see that 0xFF is 11111111B and 0x0F is 00001111B. Very simple.
Now, there are three basic logic operations you can perform on bits, plus one more that is a composite of the others:
1. Inversion (AKA "NOT") with the ~ operator. You change each bit to the opposite value:
~0 = 1
~1 = 0
2. AND with the & operator. You AND two bits together and the result will be 1 only if both bits are one:
0 & 0 = 0
0 & 1 = 0
1 & 0 = 0
1 & 1 = 1
3. OR with the  operator. You OR two bits together and the result will be 1 if either or both are one:
0  0 = 0
0  1 = 1
1  0 = 1
1  1 = 1
3. ExclusiveOR (XOR) with the ^ operator. You XOR two bits together and the result will be 1 if the two bits are different and zero if they are the same:
0 ^ 0 = 0
0 ^ 1 = 1
1 ^ 0 = 1
1 ^ 1 = 0
When you apply these operations bitwise in C, you pair up the bits in the same corresponding position (eg, the two bits both in the 128's position). For example:
01011010B & 00001111B = 00001010B
01011010B & 10000000B = 00000000B
10101010B & 10000000B = 10000000B
You can also shift a bit pattern to the left (<<) or to the right (>>); zeroes are shifted in and the bits that get shifted out are gone ("They drop into the bit bucket."). For example:
00000101B = 0x05 = 5
00000101B << 1 = 00001010B = 0x0A = 10
00000101B << 2 = 00010100B = 0x14 = 20
00000101B << 3 = 00101000B = 0x28 = 40
00000101B << 4 = 01010000B = 0x50 = 80
You will notice that the same thing happens in binary as happens in decimal when you shift digits to the left. In decimal, every time you shift left you multiply by 10: 5, 50, 500, 5000, 50,000. In binary, every time you shift left you multiply by 2: 5 × 2 = 10 × 2 = 20 × 2 = 40 × 2 = 80. Similarly, each time you shift right, you divide by the base; eg:
01010000B = 0x50 = 80
01010000B >> 1 = 00101000B = 0x28 = 40
01010000B >> 2 = 00010100B = 0x14 = 20
01010000B >> 3 = 00001010B = 0x0A = 10
01010000B >> 4 = 00000101B = 0x05 = 5
Now the only piece left to fill in the gaps in your knowledge is the most obviously one.
Binary numbers consist of a set number of bits. An 8bit number has eight bits. A 16bit number has sixteen bits. No more, no fewer. If you try to store a value in a number and the value needs more bits than the number has, then in C only the lowerorder bits will be stored; the higherorder bits will be lost (for some unknown reason, that bit bucket never fills up).
In the code snippet, unint16_t is a 16bit unsigned integer datatype and uint8_t is an 8bit unsigned integer datatype. I will forego explaining signed vs unsigned and Two's Complement format for the time being.
And now you know enough to be able to see for yourself what that code snippet does. Here it is again:
Code:
uint16_t read_blk;
NANDcmd[3] = 0;
NANDcmd[4] = 0;
NANDcmd[5] = 0;
for (read_blk=0; read_blk<4100; read_blk++)
{
NANDcmd[3] = (uint8_t)((read_blk<<7) & 0x80);
NANDcmd[4] = (uint8_t)((read_blk>>1) & 0xFF);
NANDcmd[5] = (uint8_t)((read_blk>>9) & 0x0F);
}
BTW, there's a slight trick that the author had played on you. That forloop iterates 4100 times, but each time you go through that loop you overwrite the results of the previous iteration. That means that the only iteration that means anything at all is the very last one, where read_blk equals 4099, which is 0x1003. You may consider that a gift.
PS
I would say:
NANDcmd[3] = 0x80
NANDcmd[4] = 0x01
NANDcmd[5] = 0x08
You can see why.
Comments on this post
Last edited by dwise1_aol; September 17th, 2013 at 05:10 PM.