Welcome to the Embedded Systems Programming course. My name is Miro Samek and in this lesson I'll show you how to use the bit-wise operators in C to blink all the colors of the composite LED on the Launchpad board. As usual, let's start with making a copy of the previous "lesson5" project and renaming it to "lesson6". If you are just joining the course, you can download the previous projects from state-machine.com/quickstart. Get inside the new "lesson6" directory and double-click on the workspace file to open the IAR toolset. If you don't have the IAR toolset, go back to "lesson0". So, this is the program you created in "lesson5". The program starts with configuring the GPIO pins connected to the three-color LED, then it enters an endless loop in which it turns the red LED on, waits a bit in a delay loop, and turns the red LED off, waits a bit again, and loops back. The result is blinking of the red LED. In this lesson, your objective is to use the other colors of this composite LED, such as the blue and green colors. Suppose that you want to turn the blue LED on and keep it on all the time while you blink the red component on and off. How would you do that? The first step is simple. You need to turn the GPIOF data bit 2 corresponding to the blue LED before the endless loop. But then, inside the loop, when you turn the red LED on, you got a problem. When you set the bit-1 for the red LED, you also clear all other bits, including the bit-2 for the blue LED, because all the LED bits live inside a single register So, what you really need is a method of setting and clearing the individual bits, without inadvertently disturbing the other bits. And this is where the bit-wise C operators come in. So, let's learn about the bit-wise operators in C by experimenting with them in the code. Define a couple of unsigned integer variables with some initial values, and the variable c for holding the results of various bit-wise operations. Now, let's first write the code for testing all the six bit-wise operators available in C, and let me hold on with explanations until you actually see the code in action inside the debugger: this is bit-wise OR this is bit-wise AND this is bit-wise exclusive OR this is bit-wise bit inversion, also known as one's complement this is the right bit-shift and finally, this is the left bit-shift operator Before compiling and running the code, please change the optimization level to None, and the debugger to Simulator, since you don't really need the Launchpad board. Now, compile the code by pressing F7 Let's run this code in the debugger by pressing the "Download and Debug" button. Single step over the initialization of a, b, and c and go to the Locals window to adjust the view to the binary format for. Step over the bit-wise OR expression and examine the result in the c variable. As you can see, the bit-wise OR operator performs the logical OR between each bit of a and each bit of b. If you remember the truth-tables from your elementary school, you can verify easily verify that: false, corresponding in binary to 0, OR true, corresponding to 1 is true-that is one. 1 OR 0 is 1, 1 OR 1 is 1, and 0 OR 0 is 0. In the disassembly window you can see, that the all these OR operations on all 32-bits of the two operands are performed in just one machine instruction ORRS, which is very fast and efficient. The bit-wise AND operator performs the logical AND between each bit of a and each bit of b. If you remember the truth-table for logical AND, you can verify easily verify that: 0 AND 1 is 0. 1 AND 0 is 0, 1 AND 1 is 1, and 0 AND 0 is 0. In the disassembly window you can see, that the all these AND operations on all 32-bits of the two operands are performed in just one machine instruction ANDS The bit-wise Exclusive-OR operator performs logical Exclusive-OR between each bit of a and each bit of b. You can verify that: 0 XOR 1 is 1, 1 XOR 0 is 1, 1 XOR 1 is 0, and 0 XOR 0 is 0. In the disassembly window you can see, that the all these Exclusive OR operations on all 32-bits of the two operands are performed in just one machine instruction EORS. The bit-wise NOT operator is unary, meaning that it acts on just one operand, in which it turns every 1 bit to 0 and 0 to 1. In the disassembly window you can see that bit-wise NOT is performed by the MVNS instruction, which stands for move-negative. The right bit-shift operation shifts all the bits in the first operand by the number of places specified in the second operand. For the shift by 1, this corresponds to integer division by 2, as you can verify with a calculator. In the disassembly window you can see that the right-shifting is performed by the RSRS instruction. Please note that the RSRS instruction shifts zeros into the most significant bit positions. The left bit-shift operation shifts all the bits in the first operand to the left by the number of places specified in the second operand. For the shift by 3, this corresponds to integer multiplication by 2 to the power 3, which is 8. But you need to be careful, because for a large first operand, like in this case, some of the most significant bits might "fall off the left edge", which simply means that the result after the shift no longer fits in the 32-bits. In the disassembly window you can see that the left-shifting is performed by the LSLS instruction. Please note that the LSLS instruction shifts zeros into the least significant bit position. So, now you know how the bit-wise operators work on unsigned numbers. For signed numbers, the right-shift operator, works significantly different, however. Let's perform an additional experiment. Define a signed integer x and initialize it with a positive value. Define another signed integer y and initialize it with a negative value. Next, perform right-shift of x by a couple of places. And finally perform right-shift of y by the same number of places. Let's compile and test it. As you can see, the positive value is shifted right exactly as before, that is, zeros are shifted into the most significant bit position. When you compare the decimal values of z and x, you can see that right-shift by 3 places corresponds to division by 8, which is 2 to the power of 3, as expected. However, the right-shift of the negative value y behaves completely differently than before, because now 1s are shifted to the most-significant bit. So, you've just found out that right-shifting of a signed integer shifts zeros into the most-significant bit, when the bit is zero before the shift, and ones when the bit is one before the shift. This is called sign-extending of a negative value in the 2's complement representation, which you learned in Lesson-1. This sign-extending is necessary to preserve the correspondence between right-shifting and division by a power of 2. Indeed, when you convert the values to decimal, you can see that both z and y are negative and that z is still equal to y divided by 8, which is 2 to the power 3. This difference between right-shifting of signed integers versus unsigned integers becomes very obvious when you look in disassembly. As you can see, the compiler generated the instructions ASRS for right-shifting of signed numbers, which means Arithmetic right shift, whereas the compiler generated the instruction LSRS, logical-right-shift, for right-shifting of unsigned numbers. As an embedded systems programmer, you need to know the bit-wise C operators inside and out, and in fact questions about various nuances, such as logical shift versus arithmetic shift come quite often during the embedded programming job interviews. More importantly, though, the bit-wise operators are very useful, and you will take advantage of them right away in your "blinky" program. For starters, you can now define the GPIO bits that control various LED colors by means of the bit-shift operators. For example, the red LED corresponds to bit 1, blue LED to bit 2, and green LED to bit 3. Please note that these bit-shift expressions are compile-time constants, so there is absolutely no overhead compared to defining LED_GREEN as 0x08, say. But the advantage here is that you immediately see the bit number as the shift displacement. For low-order bits this advantage is perhaps not that impressive, but for high-order bits, like, say, bit-18, it is not that easy at all to see that this is equivalent to 0x4000, while it is obvious in the expression 1 right-shifted by 18. This way of defining bit constants has saved me a lot of time counting bits and prevented a lot of stupid bugs in my programs, so I highly recommend it. After defining the macros for the LED colors, you can replace the cryptic hex numbers, which greatly improves the readability of the code. In fact, your code becomes self-explanatory, and the comment becomes redundant. Now, let's tackle the really interesting case of setting the red-color bit in the GPIOF without extinguishing the blue color. For this you can use the bit-wise OR operator between the current value of the GPIOF data register and the red-color bit. This works, because the bit-wise OR between any bit in GPIOF and LED_RED preserves the original GPIOF bit, for all bits where LED_RED is zero, and forces bit number 1 to 1. Please note that this trick works only if you actually can read from and write to the GPIOF register, so you need to check in the Data Sheet that this register has Read/Write permissions. The C language provides a special abbreviation notation for assignments in which the left hand side also appears as the first argument on the right hand side. You can use the operator-equals notation, which means exactly the same as the line above. So, finally, here is the most succinct code for setting the LED_RED bit in the GPIOF register. Please remember this as a coding idiom for setting a bit in C. To clear the LED_RED bit in the GPIOF register, you need to use the bit-wise AND operator with the complement of the LED_RED bit. This works, because the bit-wise AND between any bit in GPIOF and ~LED_RED preserves the original GPIOF bit, for all bits where ~LED_RED is 1, and forces bit number 1 to 0. Again, you can use the operator-equals notation to represent this operation more succinctly. Please remember this as a coding idiom for clearing a bit in C. Now that you know the coding idioms you can step back and look at your code a bit more critically. For example, the turning the blue-LED on is also setting a bit in the GPIOF register, so it should be coded with the bit-set idiom. Actually, all of the lines above also perform setting of bits in various registers, so they too should be coded with the bit-set idiom. Please remember, however, that you need to check in the Data Sheet that the registers have read/write permissions. And finally, you can use your LED macros to further improve the readability of your code. Before you re-compile, go to the project options and set the optimization level back to high and the debugger to TI Stellaris. Let's load the program into the Launchpad board and run it. As you can see the blue-LED is on all the time, and the fainter red-LED keeps blinking. Break into the code and set breakpoints at setting and clearing the red-LED bit. As you can see, setting of the red LED bit happens as a sequence of load-modify-store operations, whereas the bit-wise ORR machine instruction is used to modify the data. The clearing of the red-LED bit happens as another load-modify-store sequence, whereas interestingly, the compiler generated the beautiful code of just one BIC (bit-clear) instruction for clearing the bit. This is quite remarkable, because the compiler didn't literally follow your code to perform a bit-wise AND with the complemented bitmask. Instead, the compiler clearly understood your intent to clear the bit, and generated an even better code for it. I'd like you to remember this example, because it shows you that by following established coding idioms, like the idiom for clearing a bit, allows the compiler to understand your code at a higher level of your intent, not just the low-level operations. This concludes this lesson about the bit-wise operators in C. Now you know how to set, clear, toggle, and shift bits in all sorts of registers. So congratulations! In the next lesson, I'd like to answer several questions about the GPIO DATA register that were asked in the comments on YouTube. This subject actually complements quite well the discussion of the bit-wise operators, because the Stellaris GPIO DATA register demonstrates a very different, hardware-assisted approach to manipulating whole groups of bits.. If you like this channel, please subscribe to stay tuned. You can also visit state-machine.com/quickstart for the class notes and project file downloads. --- Course web-page: http://www.state-machine.com/quickstart YouTube playlist of the course: http://www.youtube.com/playlist?list=PLPW8O6W-1chwyTzI3BHwBLbGQoPFxPAPM