Logic Lab mini-course (#2307)

* Logic Lab mini-course

* example syntax
This commit is contained in:
Galen Nickel 2019-07-23 09:46:42 -07:00 committed by Peli de Halleux
parent 23e2f52193
commit b0420a8749
17 changed files with 622 additions and 0 deletions

View File

@ -169,6 +169,11 @@
* [Build](/courses/ucp-science/rocket-acceleration/build)
* [Setup and procedure](/courses/ucp-science/rocket-acceleration/setup-procedure)
* [Resources](/courses/ucp-science/rocket-acceleration/resources)
* [Logic Lab](/courses/logic-lab)
* [Logic and Expressions](/courses/logic-lab/expressions)
* [Boolean Elements](/courses/logic-lab/elements)
* [Logic Explorer](/courses/logic-lab/explorer)
* [Logic Gates](/courses/logic-lab/logic-gates)
## #reference

View File

@ -63,6 +63,11 @@ Tutorials, lessons, and mini-courses about programming and computing.
"description": "YouTube video tutorials produced by the SparkFun team!",
"url": "https://youtu.be/kaNtg1HGXbY?list=PLBcrWxTa5CS0mWJrytvii8aG5KUqMXvSk",
"imageUrl": "https://i.ytimg.com/vi/kaNtg1HGXbY/hqdefault.jpg"
}, {
"name": "Logic Lab",
"description": "Learn the basics of logic and conditional expressions.",
"url":"/courses/logic-lab",
"imageUrl":"/static/courses/logic-lab.png"
}]
```

14
docs/courses/logic-lab.md Normal file
View File

@ -0,0 +1,14 @@
# Logic Lab
![Logic lab header image](/static/courses/logic-lab/logic-lab-header.jpg)
A basic aspect of knowledge and understanding is whether something is true or not. Considering conditions around you and making a conclusion about something being true or false means that you are using logic. Computers and, in fact, all of digital electronics rely on this idea of logic to process information and give results in terms of conditions being true or false. Logic is used almost everywhere in the programs you write in places where you want decide to do one task or another.
## Logic topics
These topic sections teach you about applying logic to conditions and using Boolean algebra to express them. Also, you will see how logical operators work and how they combine to form more complex logic structures.
* [Logic and Expressions](/courses/logic-lab/expressions)
* [Boolean Elements](/courses/logic-lab/elements)
* [Logic Explorer](/courses/logic-lab/explorer)
* [Logic Gates](/courses/logic-lab/logic-gates)

View File

@ -0,0 +1,207 @@
# Boolean elements
Whether creating equations in Boolean algebra or using them in your programs, you'll form both simple and complex logical expressions that use basic operations to combine the logical conditions.
## Notation
Boolean (logical) equations are expressed in a way similar to mathmatical equations. Variables in Boolean expressions though, have only two possible values, ``true`` or ``false``. For an equation using a logical expression, the equivalant sides of the equal sign ,``=``, will be only ``true`` or ``false`` too.
The following list shows the basic notation elements for Boolean expressions.
* ``~A``: the inverse (**NOT**) of ``A``, when ``A`` is ``true``, ``~A`` is ``false``
* ``A + B``: the value of ``A`` **OR** ``B``
* ``A · B``: the value of ``A`` **AND** ``B``
* ``A ⊕ B``: the value of the exclusive OR (**XOR**) of ``A`` with ``B``
* ``Q``: equivalent result (OUTPUT) value of a logical expression
A resulting value, ``Q``, from a logical expression in is shown like:
``Q`` = ``A + B``
An equation to show logically equivalent expressions (where both sides have the same resulting value) can look like this:
``~(A + B)`` = ``~A · ~B``
## Logical operators
All Boolean expressions result from a combination of conditions and operators. These operators join individual conditons together and evaluate into a single ``true`` or ``false`` condition. The following are the basic logical operators. Their use in both Boolean algebra and in code is shown along with their truth table.
### Identity
Identity means that a result value is the same as the condition itself.
``Q = A``
```block
let A = false
let Q = A
```
#### Example - Blink LEDs on press
```blocks
let A = false
basic.forever(function () {
A = input.buttonIsPressed(Button.A)
if (A) {
basic.showIcon(IconNames.Chessboard)
} else {
basic.clearScreen()
}
basic.pause(100)
})
```
#### Truth table
A | A
-|-
F | F
T | T
### NOT (Negation)
The NOT operator is called negation or the inverse. It takes a single logical value and makes it have the opposite value, ``true`` goes to ``false`` and ``false`` goes to ``true``.
``Q = ~A``
```block
let A = false
let Q = !(A)
```
#### Example - Blink LEDs on not pressed
```blocks
let A = false
basic.forever(function () {
A = input.buttonIsPressed(Button.A)
if (!(A)) {
basic.showIcon(IconNames.Chessboard)
} else {
basic.clearScreen()
}
basic.pause(100)
})
```
#### Truth table
A | ~A
-|-
F | T
T | F
### OR (Disjunction)
The OR operator results in ``true`` when one or more conditions are ``true``.
``Q = A + B``
```block
let A = false
let B = false
let Q = A || B
```
#### Example - Blink on any press
```blocks
let A = false
let B = false
basic.forever(function () {
A = input.buttonIsPressed(Button.A)
B = input.buttonIsPressed(Button.B)
if (A || B) {
basic.showIcon(IconNames.Chessboard)
} else {
basic.clearScreen()
}
basic.pause(100)
})
```
#### Truth table
A | B | A + B
-|-|-
F | F | F
T | F | T
F | T | T
T | T | T
### AND (Conjunction)
The AND operator requires that all conditions are ``true`` for the result to be ``true``.
``Q = A · B``
```block
let A = false
let B = false
let Q = A && B
```
#### Example - Blink on double press only
```blocks
let A = false
let B = false
basic.forever(function () {
A = input.buttonIsPressed(Button.A)
B = input.buttonIsPressed(Button.B)
if (A && B) {
basic.showIcon(IconNames.Chessboard)
} else {
basic.clearScreen()
}
basic.pause(100)
})
```
#### Truth table
A | B | A · B
-|-|-
F | F | F
T | F | F
F | T | F
T | T | T
### XOR (Exclusive OR) #xor
Exclusive OR (XOR) means that only one or the other condition is true. Both conditions can't be true at the same time. XOR is common in Boolean algebra but it has no operator in JavaScript. Its operation can be made from combining a few simple expressions.
``Q = A ⊕ B``
```block
let A = false
let B = false
let Q = (A || B) && !(A && B)
```
#### Example - Blink on one press or the other
```blocks
let A = false
let B = false
basic.forever(function () {
A = input.buttonIsPressed(Button.A)
B = input.buttonIsPressed(Button.B)
if ((A || B) && !(A && B)) {
basic.showIcon(IconNames.Chessboard)
} else {
basic.clearScreen()
}
basic.pause(100)
})
```
#### Truth table
A | B | A ⊕ B
-|-|-
F | F | F
T | F | T
F | T | T
T | T | F

View File

@ -0,0 +1,162 @@
# Logic explorer
As a way to see how the basic logical operators work, we'll make a program to test them with all their possible input values.
## Inputs and output
Make an array called ``||variables:inputs||`` with two values, ``false`` and ``true``, as logical inputs. Add another variable ``||variables:Q||`` to receive the resulting value of a logical expression as output.
```blocks
let inputs = [false, true]
let Q = false
```
## Single input loop
To start with, we'll make a single input test for the variable ``||variables:A||``. The output, in variable ``||variables:Q||``, for the logical operator test will display an icon on the LEDs. A ``true`` value shows a ``t-shirt`` and ``false`` will show a ``small diamond``.
1. Get a ``||loops:for element||`` loop and put it in the ``||loops:on start||``. Rename the ``||variables:index||`` variable to ``||variables:A||`` and switch the ``||variables:list||`` variable to ``||variables:inputs||``.
2. Pull a ``||variables:set Q to||`` block into the ``||loops:for element||`` loop and set the value to ``||logic:false||``.
3. Go find the ``||logic:if then else||`` and put in below the ``||variables:set Q to||``. Pick up a ``||variables:Q||`` in ``||variables:VARIABLE||`` and drop it onto the ``||logic:false||`` to replace it.
4. Move a ``||basic:show icon||`` inside the ``||logic:if then||`` section and change the image to a ``t-shirt``. This is our image for a ``true`` output.
5. Move a ``||basic:show icon||`` inside the ``||logic:else||`` section and change the image to a ``small diamond``. This is our image for a ``false`` output.
6. Just below the ``||logic:if then else||``, put in a ``||loops:pause||``, a ``||basic:clear screen||``, and another ``||basic:pause||`` block. Set the time for each ``||basic:pause||`` to ``500``.
```blocks
let inputs = [false, true]
let Q = false
for (let A of inputs) {
Q = false
if (Q) {
basic.showIcon(IconNames.TShirt)
} else {
basic.showIcon(IconNames.SmallDiamond)
}
basic.pause(500)
basic.clearScreen()
basic.pause(500)
}
```
## Identity test
The identity test is simple. It just makes the output have the same logical value as the input. Set the ``||variables:Q||`` output variable to the ``||variables:A||`` variable.
```block
let A = false
let Q = A
```
### Identity truth table
For the Identity test, these output values will show for the inputs:
A | Q = A
-|-
**false** | ``[basic.showIcon(IconNames.SmallDiamond)]``
**true** | ``[basic.showIcon(IconNames.TShirt)]``
## NOT test
Negation, or inversion, makes the output have the opposite value of the input. So, the output value is NOT the same as the input. Since there are only two possible values, the output is the other value that is NOT the input.
Replace the ``||logic:false||`` in the ``||variables:Q||`` equation with a ``||logic:not||`` operator. Pull the ``||variables:A||`` variable down from the ``||loops:for element||`` loop and drop it inside the ``||logic:not||`` operator.
```block
let A = false
let Q = !A
```
### NOT truth table
For the NOT test, these output values will show for the inputs:
A | ~A
-|-
**false** | ``[basic.showIcon(IconNames.TShirt)]``
**true** | ``[basic.showIcon(IconNames.SmallDiamond)]``
## Two input loop
For the rest of the operator tests, we need to have another input variable. This variable comes from a second ``||loops:for element||`` loop. With one input variable there was just two possible input values. Adding a second input variable increases the number of possible input combinations by two times. Now there will be 4 different input possibilities. This will result in the truth tables having 4 rows for the operator tests.
Go get another ``||loops:for element||`` loop and put it in so that it surrounds all the inside the first loop. Rename the ``||variables:index||`` variable to ``||variables:B||`` and switch the ``||variables:list||`` variable to ``||variables:inputs||``.
```blocks
let inputs = [false, true]
let Q = false
for (let A of inputs) {
for (let B of inputs) {
Q = !A
if (Q) {
basic.showIcon(IconNames.TShirt)
} else {
basic.showIcon(IconNames.SmallDiamond)
}
basic.pause(500)
basic.clearScreen()
basic.pause(500)
}
}
```
## OR test
Now, grab an ``||logic:or||`` operator and replace the ``||logic:not||`` in the ``||variables:Q||`` equation with it. Pull the ``||variables:A||`` variable down from the outside ``||loops:for element||`` loop and drop it in on the left side the ``||logic:or||`` operator. Drag down the ``||variables:B||`` variable down from the inside ``||loops:for element||`` loop and drop it in on the right side the ``||logic:or||`` operator.
```block
let A = false
let B = false
let Q = A || B
```
### OR truth table
For the OR test, these output values will show for the inputs:
A | B | A + B
-|-|-
**false** | **false** | ``[basic.showIcon(IconNames.SmallDiamond)]``
**false** | **true** | ``[basic.showIcon(IconNames.TShirt)]``
**true** | **false** | ``[basic.showIcon(IconNames.TShirt)]``
**true** | **true** | ``[basic.showIcon(IconNames.TShirt)]``
## AND test
Now, switch the ``||logic:or||`` operator type in the ``||variables:Q||`` equation to the ``||logic:and||`` operator type:
```block
let A = false
let B = false
let Q = A && B
```
### AND truth table
For the AND test, these output values will show for the inputs:
A | B | A · B
-|-|-
**false** | **false** | ``[basic.showIcon(IconNames.SmallDiamond)]``
**false** | **true** | ``[basic.showIcon(IconNames.SmallDiamond)]``
**true** | **false** | ``[basic.showIcon(IconNames.SmallDiamond)]``
**true** | **true** | ``[basic.showIcon(IconNames.TShirt)]``
## XOR test
To test XOR, we'll use the XOR expression from [Boolean elements](/courses/logic-lab/elements#xor). Drag and place the ``||logic:LOGIC||`` blocks to make the ``||variables:Q||`` equation to look like this:
```block
let A = false
let B = false
let Q = (A || B) && !(A && B)
```
### XOR truth table
For the XOR test, these output values will show for the inputs:
A | B | A ⊕ B
-|-|-
**false** | **false** | ``[basic.showIcon(IconNames.SmallDiamond)]``
**false** | **true** | ``[basic.showIcon(IconNames.TShirt)]``
**true** | **false** | ``[basic.showIcon(IconNames.TShirt)]``
**true** | **true** | ``[basic.showIcon(IconNames.SmallDiamond)]``

View File

@ -0,0 +1,142 @@
# Logic and expressions
The use and study of _logic_ involves finding a new fact by analyzing whether some other facts together can prove to be true. Some facts, or conditions, when looked at together may prove another fact to be true, or maybe false.
If the temperature outside is below freezing and you don't have a coat, you will feel cold. If you're not sick, then you will feel well. If you can swim or ride in a boat in water, you will stay afloat. These are statements of fact that result from some condition being true.
## Truth statements
By taking some facts and putting them into a logical form, we can make an arithmetic that helps us analyze them and make a conclusion. Using the examples just mentioned, let's turn them into some logical word equations:
* ``Outside temperature is freezing`` **AND** ``I have no coat`` **=** ``I feel cold``
* **NOT** ``sick`` **=** ``I feel well``
* ``I can swim`` **OR** ``I'm in a boat`` **=** ``I'm floating``
You see the AND, NOT, and OR in the example word equations? These are our logical _operators_. Every day we make decisions when we think about one or more facts together using these operators. Sometimes, it's necessary for all facts to be true in order for the conclusion to be true. This is the case when the AND operator is used. When analyzing facts with the OR operator, only on fact needs to be true for the conclusion to be true also.
Making a decision may require more than just one or two facts. When this happens, another operator is needed to combine the facts together to make a conclusion. In the last example word equation, you actually might not be floating if just those two condtions are true. To correctly prove that you're actually floating, you need to state that you're in water too.
* **(**``I can swim`` **OR** ``I'm in a boat``**) AND** ``I'm in water`` **=** ``I'm floating``
To prove that you're floating, the two facts that you can swim or you are in a boat must be made into a single fact that is combined with the other fact that you are also in water. Otherwise, if you're able to swim but still on land, or in a boat that is on the beach, you're not not floating.
## Boolean algebra
As a way to reduce the conditions, or facts as we've called them, into a form that is more compact, an algebra was invented. George Boole made a type of arithmetic (Boolean algebra) that uses symbols for the conditions, the operators, and the result. The conditions are considered as variables that have the value of either ``true`` or ``false``. the operators like AND, OR, and NOT are single character symbols. If we want to change the statement "I'm happy when it's sunny or when I'm eating a donut" into a Boolean equation, we could start by making the conditions into variables.
* Variable ``A`` = ``"It's sunny"``
* Variable ``B`` = ``"I've eaten a donut"``
The result then, is a variable called ``Q`` that is true when you're happy and is a value of an operation of ``A`` with ``B``. This operation is OR which is represented by the ``+`` symbol.
``Q`` = ``A + B``
The result of ``Q`` is ``true`` when either it's sunny or you've had a donut. If other things make you happy, like being on vacation, you could add that to the equation.
* Variable ``C`` = ``"I'm on vacation"``
``Q`` = ``A + B + C``
It could be that you're easy to please and you just have to feel well to be happy. So, you're happy when your NOT sick. We'll use the ``~`` to mean NOT in our equation.
* Variable ``A`` = ``"I'm sick"``
``Q`` = ``~A``
In the situation where all conditions must be true for the result to be true, the conditions use the AND operation. For the sun to shine on you, the sky must be clear and it has to be daytime. We put these two facts together with the AND symbol ``·``.
* Variable ``A`` = ``"The sky is clear"``
* Variable ``B`` = ``"It's daytime"``
* Result ``Q`` = ``"The sun is shining"``
``Q`` = ``A · B``
## Expressions
Sometimes different operations on the same conditions can make equivalent results. If we take the opposite case of the last example where the sun is not shining, the variables for that are:
* Variable ``A`` = ``"The sky is clear"``
* Variable ``B`` = ``"It's daytime"``
* Result ``Q`` = ``"The sun is shining"``
* Result ``~Q`` = ``"The sun is NOT shining"``
To make the opposite of ``"the sun is shining"`` we negate, use the NOT symbol, on both sides of the equation.
``~Q`` = ``~(A · B)``
Now, let's think of the sun NOT shining due to negative conditions. If the sky isn't clear OR it's not daytime, then the sun isn't shining. So, the NOT symbol is put in before the variables for each condition so that ``"the sun is NOT shining"`` has another equation like this:
``~Q`` = ``~A + ~B``
We see that the side with the ``A`` and ``B`` variables in both equations are equivalent to each other since they both equate to ``~Q``:
``~(A · B)`` = ``~A + ~B``
The logic equation now doesn't include the result variable ``Q`` but instead there are two _expressions_ that are logically equivalent on each side.
### ~ hint
#### De Morgan's Thereom
That last equation, ``~(A · B)`` = ``~A + ~B``, demonstrates an inportant property in Boolean algebra. It's called De Morgan's Thereom which says that the inverse (NOT) of a conjunction (AND) is logically equivalent to the disjunction (OR) of two inverses (NOT). Also, the inverse (NOT) of a disjunction (OR) is logically equivalent to the conjunction (AND) of two inverses (NOT).
This easier understood by seeing the Boolean equations for both cases:
``~(A · B)`` = ``~A + ~B``
>-- AND --
``~(A + B)`` = ``~A · ~B``
### ~
## Truth tables
A truth table is a way to see all possible condtions for the variables in a logical expression and to chart the results. Using the truth statement about when it's freezing outside and you have no coat, here's the truth table showing the possible conditions and their results:
It's freezing | I have no coat | I feel cold
-|-|-
false | false | false
false | true | false
true | false | false
true | true | true
<br/>
Because you feel cold only when both conditions are true, the statement becomes an AND expression in Boolean algebra.
* Variable ``A`` = ``"it's freezing"``
* Variable ``B`` = ``"I don't have a coat"``
``A · B`` = ``Q``
A truth table for the variables in the expression have the same values as the table for the truth statement (``true`` and ``false`` are abbreviated to just ``T`` and ``F``).
A | B | Q
-|-|-
F | F | F
F | T | F
T | F | F
T | F | T
<br/>
What would happen if we changed the condition of ``"I have no coat"`` to ``"I have a coat"``? How does that affect truth table about how cold you feel?
It's freezing | I have a coat | I feel cold
-|-|-
false | false | false
false | true | false
true | false | true
true | true | false
<br/>
A | B | Q
-|-|-
F | F | F
F | T | F
T | F | T
T | F | F
<br/>
To write a Boolean equation for when you feel cold, we find the condtions in the table where ``Q`` is ``true``. Here we see that you will feel cold only in one row, when condition ``A`` is ``true`` and condtion ``B`` is ``false``. The Boolean equation for these conditions is this:
``A · ~B`` = ``Q``

View File

@ -0,0 +1,87 @@
# Logic Gates
![OR gate symbol](/static/courses/logic-lab/logic-gates/full-adder.png)
In the real world digital devices aren't the abstract logical expressions of Boolean algebra, but they are implementations of these expressions in hardware. The logical expressions are translated into device structures called _logic gates_. A logic gate is both a symbolic representation of a logical operation and, when used in digital electronics, it can is an actual circuit in hardware. A single logic gate is usually made of several transistors an shares space with many others in an integrated circuit.
Each of the basic operators we learned about in the [expressions](/courses/logic-lab/expressions) section have a gate symbol. The symbol takes the place of the operator and the variables are the inputs to the gate. The resulting value from the expression equation is the output of the gate. The output of a gate can be a final result or it can be connected as an input to yet another gate.
## Gate symbols
Logic gates are symbols that can directly replace an expression in Boolean arithmetic. Each one has a different shape to show its particular function. The inputs (Boolean variables) enter at the left of the symbol and the output leaves from the right. When combined together, several gates can make a complex logical evaluation system that has many inputs and outputs. Digital computers are designed by connecting thousands, or millions, of these gates to together.
### NOT gate
The NOT gate is a forward arrow with a small circle at the output. The circle part of the symbol is what says that the output is negating the input.
![NOT gate symbol](/static/courses/logic-lab/logic-gates/not-gate.png)
### OR gate
Th OR gate has a curved input side and a sharp pointed output.
![OR gate symbol](/static/courses/logic-lab/logic-gates/or-gate.png)
### AND gate
The AND gate has a flat input side and round output side.
![AND gate symbol](/static/courses/logic-lab/logic-gates/and-gate.png)
### Exclusive OR (XOR) gate
The exclusive or gate symbol is just like the OR gate but it has an additonal curved line crossing the inputs.
![XOR gate symbol](/static/courses/logic-lab/logic-gates/xor-gate.png)
## Combined logic
When you connect multiple gates together you have a combined logic system or _combinatorial logic_. To design a combined logic system we can use a truth tables to match logical outputs for out various input conditions. Boolean expressions are written from the conditions in the table. Then, we can directly convert the expression into a diagram of logic gates.
You might remember that back in [Boolean elements](/courses/logic-lab/elements#xor) we saw that there was no operator to use in code for XOR. It was was made up using a combination of AND, OR, and NOT operators:
```block
let A = false
let B = false
let Q = (A || B) && !(A && B)
```
Let's map the input and output conditions in a truth table for a combined logic system for XOR. We'll find all the conditions that cause a ``true`` result and create a Boolean expression for them.
A | B | A ⊕ B
-|-|-
F | F | F
F| T | T
T| F | T
T | T | F
<br/>
There are two conditions where the result column has ``true`` values. The first conditon is when ``A`` is ``false`` and ``B`` is ``true`` which is expressed as ``~A · B``. The second conditon is when ``A`` is ``true`` and ``B`` is ``false`` which is expressed as ``A · ~B``. Our XOR expression is ``true`` when one of these conditions are ``true`` which is written like:
``A ⊕ B`` = ``(~A · B) + (A · ~B)``
In code this expression is formed with these logic blocks:
```block
let A = false
let B = false
let Q = (!A && B) || (A && !B)
```
Coverting the equation to logic gates makes the following diagram. Notice how each gate "connects" the variables together just like the logic blocks in the code above.
![Combinatorial XOR first version](/static/courses/logic-lab/logic-gates/combinatorial1-xor.png)
However, if we take the other two unused conditions from the truth table that make the XOR operation ``false``, can make the negative equation for XOR, called a NXOR:
``~(A ⊕ B)`` = ``(~A · ~B) + (A · B)``
To get back to ``A ⊕ B`` we have to negate this negative equation. Then, with the help of [De Morgan's Thereom](/courses/logic-lab/expressions#de-morgan-s-thereom), we get a different equation for XOR but it's still logically equivalent to the original one.
``A ⊕ B`` = ``(A + B) · ~(A · B)``
When this equation is converted to logic gates, there's one fewer gate than in the first diagram.
![Combinatorial XOR second version](/static/courses/logic-lab/logic-gates/combinatorial2-xor.png)
This diagram has less complexity than the first one. Reduction in the number of gates to accomplish the same logical result is one of the primary goals for digital logic design. For electronic devices, this allows more gates to use the limited amount of space on an integrated circuit.

BIN
docs/static/courses/logic-lab.png vendored Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 21 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 9.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 24 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 26 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 43 KiB