Time to learn about bitwise and shift
TommyBoy
Posts: 9
Hello Everyone -
I'm revisiting electronics and programming after being away from it for 20 years, and I've been following the C Tutorials. I got to the Sony IRC lesson and decided to branch off because my remote wasn't a Sony, but something else. I found that it uses NEC protocol. I've researched the device and I've developed fully functioning source code to:
1) Detect pulses on the IR detector,
2) Store the length of the pulses in an array,
3) Decode the pulse lengths into '1's and '0's,
4) Convert the LONG bits into an INT, and
5) Perform some function when I press a key.
-
Everything works as it should, but I'm storing and converting a LONG when I really need to store a BIT.
One area where my re-education is lacking is in the use of Bitwise and shift operators. I have a sense that I'll be needing a lot of these. My little program might be a good place to demonstrate their use.
Can someone please demonstrate a more efficient way to get the bits into an INT format using Bitwise and shift operators? Heavy emphasis on the explanations please.
Thanks.
I'm revisiting electronics and programming after being away from it for 20 years, and I've been following the C Tutorials. I got to the Sony IRC lesson and decided to branch off because my remote wasn't a Sony, but something else. I found that it uses NEC protocol. I've researched the device and I've developed fully functioning source code to:
1) Detect pulses on the IR detector,
2) Store the length of the pulses in an array,
3) Decode the pulse lengths into '1's and '0's,
4) Convert the LONG bits into an INT, and
5) Perform some function when I press a key.
-
Everything works as it should, but I'm storing and converting a LONG when I really need to store a BIT.
One area where my re-education is lacking is in the use of Bitwise and shift operators. I have a sense that I'll be needing a lot of these. My little program might be a good place to demonstrate their use.
Can someone please demonstrate a more efficient way to get the bits into an INT format using Bitwise and shift operators? Heavy emphasis on the explanations please.
Thanks.
c
6K
Comments
Here is an example with numbers in a loop. Each time through the loop, it shifts the the binary values in the bits variable to the left by 1, makes a comparison, and stores the 1/0 result of that comparison in bits variable's the rightmost binary digit. As written, the code displays this result in the SimpleIDE Terminal:
bits(dec) = 3510
bits(binary) = 110110110110
You can change the (inVal % 3 < 2) condition to get a different set of 1/0 result bits.
How it Works
Before the loop starts, make sure to clear the variable that will store the result bits by setting it to zero. In this example, the for loop counts inVal from 0 to 11. Each time through the loop, the right side of the expression bits = (bits << 1) | (inVal % 3) does three things:
1) Shift all the binary values stored by bits left by one slot with (bits << 1). So, if bits stored binary 101, this operation will return 1010.
2) Get the result if a comparison. In this case, (inVal % 3 < 2) checks to find out if the remainder of inval / 3 is less than 2. So, when the remainder of inVal / 3 is 0 or 1, the the comparison returns 1. If the result of inVal / 3 is 2, well, that's not less than 2, so the comparison returns 0. Since we are dealing with int values in the Propeller, the 0 result will actually be a 32-bit variable with all zeros. The 1 result is really 000...0001, where the ... is taking the place of 25 more zeros.
3) Bitwise OR the shifted bits result from step 1 with the 1/0 result from step 2. The rule for OR is that 1 OR any value (could be 1, could be 0) is 1. If the result from step 2 was 0, the OR result would be.
...1010
...0000 OR
...1010
If the result from step 2 was 1, the result would be:
...1010
...0001 OR
...1011
Note that that all the 0s in the second number OR with values in the top number leaves the values unchanged in the result. But when we made the rightmost digit in the second number a 1, the 0 in the top number OR the 1 in the second number caused a 1 in the rightmost digit of the result.
In your case, step 2 would be a comparison of your pulse_in measurement to find out if the remote transmitted a pulse that lasted the length of time for transmitting a 1 or a 0.
That's exactly what I needed.
I reworked your code so I could see what was going on, step-by-step.
Bitwise.c
I've also revised my code to include the 'Left Shift' and 'Or' functions. It works as expected.
NEC Prot.c
'Left Shift' makes the first pulse the MSB. Is there a way to make it the LSB? I know 'Right Shift' doesn't do it.
In the line of code the comments identify as Step 3, change the for(i = 16; i < 24; i++) to for(i = 23; i > 15; i--) // Step 3. . . and your codes will come out as actually represented in the transmission. Pressing 1 will actually output a 1.
BTW, in your original statement you had for(i = 16; i < 25; i++) , looking at 9 bits instead of 8.
A simple print("%d\n", KeyBit); before the Switch statement will help you reidentify all the other buttons on your remote.
'Left Shift' makes the first pulse the MSB. Is there a way to make it the LSB? I know 'Right Shift' doesn't do it" Yes it will, just change both statements in step 4 to shift right and in the second statement change the 1 at the end ( after the OR symbol '|' to either 128 or 0x80 so that you are placing a 1 bit into the MSB position after the byte was shifted right once.
Just use one method or the other, not both.
Hal
Thanks for the reply.
Darn, I knew that at one time and I'd forgotten!
Good catch. Thanks for the pickup.
This is exactly what I was looking for.
NEC Prot.c
Here's the updated code with both suggestions incorporated. (After testing I commented out one.)
Thanks again Hal. You've given me the info I was looking for.