doc(docs): proofread the docs

This commit is contained in:
Victor Nakoryakov
2017-06-26 16:35:22 +03:00
parent af8e1b7dc5
commit eeee0d709c
9 changed files with 596 additions and 563 deletions

View File

@@ -5,63 +5,64 @@ title: Data Types
Data Types
==========
In XOD any pin have a data type. Data values are transfered along links
between nodes allowing them to work together on a whole job.
In XOD, every pin has a data type. Data values are transfered along links
between nodes, allowing them to work together to a perform a job.
This is very much like signals of ICs in electronics. Although signals in
hardware are quite limited in the sense what data they could carry. They are
simply voltage with a value somewhere between zero volts and few volts. To
express meaningful values like numbers various tricks are used. For example,
one could map voltage to a value with a logarithmic scale, or consider the
voltage a series of 0s and 1s arriving at predefined rate, then group them by
eight and convert into bytes.
This is very much like integrated circuits signals in electronics, though
hardware signals are quite limited as to what data they can carry. They are
simply voltages with a value somewhere between zero volts and few volts.
Various tricks are used to express meaningful values like numbers. For example,
you could map voltage to a value on a logarithmic scale, or you could interpet
the voltage as a series of 0s and 1s arriving at a predefined rate, and
then convert them into bytes by grouping them into sets of eight.
In XOD various data types are supported natively. There is no need to use the
XOD has native support for various data types — no need to use any
tricks. For example, there are data types that hold arbitrary numbers or
textual strings.
text strings.
<div class="ui segment">
<span class="ui ribbon label">Pro Tip</span>
<p>Perhaps you know, there are languages with static typing (C, C++, Java,
Haskell) and languages with dynamic typing (JS, Python, Ruby). Whats better
is a long flamewar.</p>
<p>You may know there are languages with static typing (C, C++, Java,
Haskell) and languages with dynamic typing (JS, Python, Ruby). A long flamewar
has been waged as to which is better.</p>
<p>XOD is in static typing camp. I.e. a pin cant have a number value now, and a
textual string value two seconds latter. This gives necessary knowledge to IDE
so that it can protect you from silly mistakes.</p>
<p>XOD is in the static-typing camp, e.g. a pin cant have a number value
now, and a text string value two seconds later. This lets the IDE protect you
from silly mistakes.</p>
</div>
As said above, the data type is a characteristic of a pin. You can say “Node
FOO has output pin BAR of number type”. That means that the BAR pin
carries a number value at any particular node. You can also say “Node FOO has
As mentioned above, a data type is a characteristic of a pin. You can say
“Node FOO has output pin BAR of number type”. That means that the BAR pin
carries a number value in every FOO node. You can also say “Node FOO has
input pin QUX of boolean type”. That means the FOO node always expects 0 or 1
value connected to its QUX pin.
One important division of types in XOD is between a *pulse type* and any other
type that are together called *value types*. All them described below.
Importantly, XOD types are divided between *pulse types* and all other types,
which are collectively known as *value types*. Each type is described below.
Pulse type
----------
Pulse type is a very special type because it actually dont carry any data on
its own. It is only used to tell about something happened just now or something
is required to happen right now.
The pulse type is very special, because it doesn't actually carry any data on
its own. It is only used to indicate that something has just happened or that
something should happen right now.
Pulses are similar to clock or interrupt signals in digital electronics.
All were interested in is *moments* when the signal rises to Vcc or falls to
ground. They dont carry any additional useful information in them.
All were interested in is the *moments* when the signal rises to Vcc or
falls to ground. They dont carry any additional useful information.
A pulse signal can tell us that weve got a new TCP packet from network, that
a button was pressed, that some timeout has been past. We would use a pulse
signal to trigger SMS send or to adjust motor speed.
A pulse signal can tell us that weve got a new TCP packet from the network,
a button was pressed, or some time interval has passed. We would use a pulse
signal to trigger an SMS send command or adjust motor speed.
Very often pulse signals are accompanied with other value types on neighbour
pins. The values describe “what” whereas the pulse describes “when”.
Pulse signals are quite often accompanied by other value types on neighboring
pins. The values describe the “what”, while the pulse describes the
“when”.
Pulses make your programs live. Without them your device would stay intact.
Pulses give life to your programs. Without them, your device won't do anything.
Read [Execution Model](../execution-model/) to understand this logic in detail.
Here are short list of nodes youll use a lot working with pulses:
Here is a short list of nodes youll use a lot in conjunction with pulses:
* [`boot`](/libs/xod/core/boot/)
* [`clock`](/libs/xod/core/clock/)
@@ -71,13 +72,14 @@ Here are short list of nodes youll use a lot working with pulses:
Boolean type
------------
Boolean value can be either *true* or *false*. You can also think of it as a
choice between of one/zero, yes/no, on/off, high/low, enabled/disabled.
Boolean values can be either *true* or *false*. Alternatively, you can think of
them as a choice between of one/zero, yes/no, on/off, high/low, or
enabled/disabled.
Logical values are ubiquitous. They are enough to express values of simple
Logical values are ubiquitous. They are adequate to implement simple
digital sensors (is a button pressed or not?), control simple actuators (should
a relay close?), and carry results of logical operations (is temperature
greater than 25°?).
a relay close?), and carry the results of logical operations (is the
temperature greater than 25°?).
Here are short list of nodes youll use a lot working with logical values:
@@ -89,20 +91,20 @@ Here are short list of nodes youll use a lot working with logical values:
Number type
-----------
Numbers are widespread. The numeric data type is used to transfer sensors
measured values, set speed of motors, perform arithmetical computations,
comparisons and so on.
Numbers are everywhere. The number data type is used to transfer sensor
readings, set motor speeds, perform arithmetic computations and
comparisons, and so on.
Number type values in XOD can represent fractional numbers, positive and
Number values in XOD can be fractional numbers and positive and
negative infinity.
Precision and most extremal representable values depend on capabilities of a
target platform. In any case it would be enough to operate on numbers with
six significant digits in range ±10<sup>38</sup>.
Precision and the range of representable values depend on the capabilities of
the target platform. In any event, the number type is enough to operate on
numbers with six significant digits in range ±10<sup>38</sup>.
<div class="ui segment">
<span class="ui ribbon label">Pro Tip</span>
The underlying type for numerical values is IEEE 754 floating point with
The underlying format for number values is IEEE 754 floating point with
single or double precision. It depends on a target platform.
</div>
@@ -120,54 +122,56 @@ Here are some nodes youll use to work with numbers:
### Unit ranges
Many nodes use numbers in range from 0 to 1. It is handy if the value denote
some kind of percentage. For example, a potentiometer node
uses 0.0 to denote leftmost washer position, 0.5 to denote middle position,
and 1.0 to express rightmost position.
Many nodes use numbers in the range from 0 to 1. This is convenient if the
value denotes some kind of percentage. For example, a potentiometer node
uses 0.0 to denote the leftmost washer position, 0.5 to denote the middle
position, and 1.0 to denote the rightmost position.
Another example is an LED node. 0.0 is used to turn it off, 0.33
to emit 33% brightness and 1.0 to turn on at maximum brightness.
to emit 33% brightness and 1.0 to turn on it at maximum brightness.
Some nodes use ranges from -1 to 1. E.g. motor node use -1 for
full backward, -0.2 for 20% backward, 0 to stop and 1 to run full forward.
Some nodes use ranges from -1 to 1. For example, a motor node use -1 for
full backward, -0.2 for 20% backward, 0 to stop, and 1 to run full forward.
Unit ranges are easy to operate with although theyre purely conventional.
Its up to a node implementation to decide what to do if an input value falls
out of the range. Usually theyll clamp the input to a desired range.
Unit ranges are convenient to use, but entirely unnecessary.
Its up to a node's implementation to decide what to do if an input value
falls out of the range. A common behavior is to clamp the input to the desired
range.
String type
-----------
Strings represent pieces of text like “Hello World!”.
Unlike some languages where strings are threated specially in XOD its just a
list of bytes. Thus its up to you to control text encoding. You can choose
ASCII, UTF-8 or old-school CP-1252 for storage. What would work best depends
on capabilities of hardware modules and data transfer formats you work with.
Unlike some languages that give strings special treatment, XOD considers them
to be just a list of bytes. Thus its up to you to manage text encoding. You
can choose ASCII, UTF-8, or old-school CP-1252 for storage. The best choice
depends on the hardware modules and data transfer formats you work with.
Computers dont like text actually, but humans are. Youll use text to parse a
high-level input like SMS or tweet and to present values back to human on
display or via some web-service.
Computers dont actually like text, but humans do. Youll use text to parse
high-level input like an SMS or tweet, and display values to humans, or send
them via some web-service.
<div class="ui segment">
<span class="ui red ribbon label">XOD T0D0</span>
All types described below are not yet implemented in XOD. For now, its just
a description of how things <em>could</em> look like in future. Were welcome you
to the <a href="//forum.xod.io">discussion on our forum</a>. Here you can
affect the design decisions.
The types described below are not yet implemented in XOD. For now, we'll just
describe how things <em>could</em> look in future. We invite you
to join the <a href="//forum.xod.io">discussion on our forum</a>. You could
affect our design decisions.
</div>
Integer type
------------
Although in many cases number type is enough to process numerical values,
sometimes its more preferrable to work on integer type.
Although the number type is often enough to process numeric values,
sometimes its preferrable to work with an integer type.
It have no problems with precission loss, operated faster by processors and
have much more sense for some functions such as as getting a substring from
Integers have no problems with precision loss, are processed faster, and
make much more sense for some purposes, such as as getting a substring from
a string at a particular index and of a particular length.
Integer values can represent integral values from rougly ±2 milliards range.
The integer type can represent integral values in the range of rougly ±2
billion.
<div class="ui segment">
<span class="ui ribbon label">Pro Tip</span>
@@ -177,79 +181,79 @@ The underlying type for integer values is a signed 32-bit integer.
Byte type
---------
Bytes are fundamental building blocks of low-level computing. Many hardware
peripherals send or consume series of bytes to interact with a controller.
Bytes are the fundamental building blocks of low-level computing. Many hardware
peripherals send or consume a sequence of bytes to interact with a controller.
In XOD byte is a distinct data type that is used to perform low-level
operations. It cant be interchanged with other types directly. Youll
use some conversion nodes to convert byte values to more useful types and
back. They are:
In XOD, a byte is a distinct data type that is used to perform low-level
operations. It cant be directly interchanged with other types. Youll
use some conversion nodes to convert byte values to and from more useful types
such as:
Tuples
------
Tuples are simply groups of other values with a predefined order and size.
Say, `Tuple3 Number Number Number` could be used to denote a point in 3D-space.
In that case it would contain X at first position, Y at second, and Z at
third.
For example, `Tuple3 Number Number Number` could be used to denote a point in
3D-space. In that case, it would contain X in the first position, Y in second,
and Z in the third.
Or `Tuple2 Byte Integer` could be used to describe a message for a particular
I²C chip.
Or `Tuple2 Byte Integer` could be used to encode a message for a particular IC
chip.
<div class="ui segment">
<span class="ui ribbon label">Pro Tip</span>
If youre familar with C or Arduino think of tuples as of structs in which
If youre familar with C or Arduino, think of tuples as structs whose
members are accessed by their index rather than by their name.
</div>
You can easily pack and unpack single values to or from tuples using following
nodes:
You can easily pack and unpack single values to and from tuples using the
following nodes:
Lists
-----
Lists are sequences of values of a particular type. Unlike tuples their length
is not predefined: they could grow or shrink as program goes. And they can only
contain values of a single type.
Lists are sequences of values of a particular type. Unlike tuples, their length
is not predefined: they can grow or shrink as the program runs. And they can
only contain values of a single type.
For example:
- `List Number` can represent a history of temperature readings
- `List Byte` can be a packet to send or receive from the network
- `List (Tuple Number Number Number)` can represent a trajectory for a robotic
hand as a sequence of points in 3D-space.
- `List (List Number)` represents a 2D-table of numbers with dynamic size.
- `List Byte` might be a packet to send or receive from the network
- `List (Tuple Number Number Number)` could represent the trajectory of a
robotic hand as a sequence of points in 3D-space.
- `List (List Number)` represents a dynamically-sized 2D-table of numbers.
Common operations on lists include:
Errors
------
Error is not an independent type per se. It rather augments other types with
special values to denote errors in computations.
Error is not an independent type per se. Instead, it augments other types with
special values to denote computational errors.
For example, a division of an integer on zero would result in error value
rather than integer value. The same way an attempt to get an element from
For example, dividing an integer by zero would result in error value
rather than integer value.Similarly, an attempt to get an element from
an empty list would result in another error value.
Error values are viral. Once a functional node gets an error value on one of
its inputs all it outputs get error values too.
There are few nodes that you would use to generate your own errors and
to handle potentially errorish values.
There are few nodes that you would use to generate your own errors and handle
potential errors.
Casting rules
-------------
What should happen if a pin of one type is connected to a pin of another
type? Some combinations are forbidden and youll get an error if try to link
two pins of these types. Other combinations are valid and *casting* between two
is done behind the scenes.
type? Some combinations are forbidden and youll get an error if you try to
link such pins. Other combinations are valid, and values are *cast* from one
type to another.
In many cases you would like to convert a signal value from one type to
another. I.e. to link a pin with one type to a pin of another type.
It is often desirable to convert a signal value from one type to
another, i.e. to link a pin with one type to a pin of another type.
For some type pairs this is possible without any intermediate conversion
For some type pairs, this is possible without any intermediate conversion
nodes:
<table class="ui definition single line table">
@@ -278,7 +282,7 @@ nodes:
<td></td>
<td class="disabled">use nodes</td>
<td class="disabled">use nodes</td>
<td>3.14159 →<br/>"3.14"<br/>(two digits<br/>after dot)</td>
<td>3.14159 →<br/>"3.14"<br/>(two digits<br/>after decimal)</td>
</tr>
<tr>
<td>Integer →</td>
@@ -307,7 +311,7 @@ nodes:
</tbody>
</table>
Other convertions cant always be done unambigously thus are not allowed.
Other convertions cant always be done unambigously and thus are not allowed.
Use additional nodes to make casting explicit in such cases:
* [`format-number`](/libs/xod/core/format-number/)
@@ -316,25 +320,25 @@ Use additional nodes to make casting explicit in such cases:
### List lifting
There are times when we have an output of a particular type `T` and an
input of corresponding list type `List T`. Or vice versa. Conceptually
input of the corresponding list type `List T`. Or vice versa. Conceptually,
these are two very different types. However, XOD can make an implicit
cast to link them properly. This transformation is known as “lifting”.
If a value of type `T` is connected to an input of type `List T`, the
value is considered to be a single element list with that value on
first position. E.g. `42` becomes `[42]`.
value is considered to be a single element list with that value in
the first position, i.e. `42` becomes `[42]`.
Vice versa, if a value of type `List T` is connected to an input of type `T` in
of a functional node that node *maps* each element of the list and its result
value gets list type. E.g. a node [absolute](/libs/xod/core/absolute/) that is
usually operate on single numbers given a list `[-1, 2, 3, -4, -5]` would have
`[1, 2, 3, 4, 5]` as a result.
Conversely, if a value of type `List T` is connected to an input of type `T` in
a functional node, the node *maps* each element of the list and the resulting
value is a list type. For example, if `[-1, 2, 3, -4, -5]` were passed to an
[absolute](/libs/xod/core/absolute/) node, which usually operates on single
numbers, the result would be `[1, 2, 3, 4, 5]`.
If two lists given as values of two inputs of a functional node the computation
is done element-wise. E.g. a node [add](/libs/xod/core/add/) given `[1, 2, 3]`
for `X` and `[40, 50, 60]`
for `Y` would output `[41, 52, 63]`.
If two lists are given as the two inputs of a functional node, the node
operates element-wise on the lists, i.e. given `[1, 2, 3]` for `X` and `[40,
50, 60]` for `Y`, the [add](/libs/xod/core/add/) node would output `[41, 52,
63]`.
When lists length differ lifting operation takes a shortest one and acts as
all lists have the same shortest length. E.g. “add” node given `[1, 2, 3, 4]`
and `[40, 50]` would output `[41, 52]`.
If the lists differ in length, the lifting operation treats each of the lists
as if it was as short as the shortest list, i.e. given `[1, 2, 3, 4]` and `[40,
50]`, the “add” node would output `[41, 52]`.

View File

@@ -1,61 +1,60 @@
---
title: Execution Model in Details
title: Execution Model in Detail
---
Execution Model in Details
===========================
Execution Model in Detail
=========================
In contrast to conventional programming, XOD is a data flow language rather
than control flow one. That means there is no such thing as an instruction
pointer that determines what command will be executed next moment. Instead,
updates are done in semi-instant *transactions* where all data is evaluated
simultaneously.
than a control flow language. That means there is no such thing as an
instruction pointer that determines what command will be executed at the next
moment. Instead, updates are done in semi-instantaneous *transactions* in which
all data is evaluated simultaneously.
Functional and effect nodes
---------------------------
There is such thing as a *function* in mathematics. Sure, you know many of them:
There is such thing as a *function* in mathematics. You know many of them:
- `f(x) = sin x` is a function of single argument that returns its sine;
- `f(r) = π × r²` is a function of single argument that returns square of a
- `f(x) = sin x` is a unary (i.e. it takes a single argument) function that
returns the sine of its argument;
- `f(r) = π × r²` is a unary function that returns the area of a
circle with given radius;
- `f(x, y) = √(x² + y²)` is a function of two arguments that returns a distance
from origin to a point with given coordinates;
- `f(v₀, a, t) = v₀ × t + (a × t²) / 2` is a function of
three arguments that returns velocity of an object at a particular moment in
time.
- `f(x, y) = √(x² + y²)` is a binary function (i.e. it takes two arguments)
that returns the distance from the origin to the point (x, y);
- `f(v₀, a, t) = v₀ × t + (a × t²) / 2` is a ternary (i.e. it takes
three arguments) function that returns the velocity of an object at a
particular moment in time.
Functions are great because they have very predictable behavior. E.g. if youre
computing circle square it will be always the same for the same radius. It is a
nonsense if the result of computation today would differ from the result of
yesterday, or if the result would change depending on other factors like
weather outside. Furthermore computing circle square of radius 2 cant affect
a result of another computation, e.g. `sin 2` now or in the future.
Functions are great, because they behave very predictably, i.e. if youre
computing the area of a circle, it will always be the same for the same radius.
It would be nonsense if the computation today differed from that of yesterday,
or if the result changed based on other factors like the weather outside.
Furthermore, computing the area of a circle with radius 2 cant affect the
result of another computation, e.g. `sin 2`, now or in the future.
Functions are intuitive and understandable pieces that dont involve side
effects in computation.
Functions are intuitive and understandable pieces that dont have
computational side effects.
<div class="ui segment">
<p><span class="ui ribbon label">Note</span>
Experienced programmers say that such functions are referrentially transparent,
easy to reason about, stateless, idempotent and pure. They mean the same things
and they loveem.
easy to reason about, stateless, idempotent, and pure.
</div>
The characteristics of functions make them ideal building blocks to compose
complex computations. Input arguments of one function could be results of
other functions. They in turn can get arguments from yet other functions, etc.
The characteristics of functions make them ideal building blocks for creating
complex computations. The results of one function can be the input arguments of
another function, which could feed its results into yet another function, etc.
However, if youre going to build a program solely from functions it would be a
program that always do the same thing and lead to absolutely same result. It
would not depend on user input, events in real world, or time. It would not
affect outside world and furthermore would have no chance to present
computation results. All because functions cant have side effects. Thus
another kind of building block is required.
However, a program consisting solely from functions would always do the same
thing and produce exactly the same result. It would not depend on user input,
real world events, or time. It would not affect the external world or have the
ability to display computational results. All because functions cant have
side effects. Thus another kind of building block is required.
In XOD there are two kinds of nodes available. *Functional nodes* represent
functions. And *effect nodes* serve as interfaces to the outside world, time,
and memory of past values.
In XOD, there are two kinds of nodes available. *Functional nodes* represent
functions. *Effect nodes* serve as interfaces to the external world, time, and
memory of past values.
### Functional nodes
@@ -63,9 +62,9 @@ Functional nodes always have inputs and output pins. All pins have [value
types](../data-types/#value). In other words functional nodes *never* have pins
of [pulse type](../data-types/#pulse).
Output values depend only on values of input pins. They cant depend on time
(only if given as an explicit input value), on parameters of outside world, or
on results of their past computations. Given the same set of input values they
Output values only depend on the values at input pins. They cant depend on
time (unless given as an explicit input value), parameters of the external
outside world, or past computations. Given the same set of input values, they
always result in the same set of output values.
Some examples of functional nodes are:
@@ -76,27 +75,27 @@ Some examples of functional nodes are:
* [`or`](/libs/xod/core/or/)
* [`format-number`](/libs/xod/core/format-number/)
Functional nodes affect nothing but their output values. They cant change
brightness of a LED or speed of a motor on their own.
Functional nodes affect nothing but their output values. On their own, they
cant change the brightness of an LED or the speed of a motor.
<div class="ui segment">
<p><span class="ui ribbon label">Note</span>
If youre an advanced Excel user think about functional nodes as of cell
If youre an advanced Excel user, think about functional nodes as cell
formulas.
</div>
### Effect nodes
Effect nodes could have just inputs, just outputs or both at once. They
*always* have pins of pulse type. Input pulses is what drives them to perform
effects and their output pulses is what tell us about effects that took place.
Effect nodes can have just inputs, just outputs, or both. Their pins
are *always* the pulse type. Input pulses drive them to perform
effects, and output pulses tell us about effects that have taken place.
A result of hitting an effect node can be arbitrary. It could turn on a lamp,
send an SMS, launch a nuke, or memoize a value for future use.
The result of activating an effect node can be arbitrary, e.g. turn on a lamp,
send an SMS, launch a nuke, or store a value for future use.
When such node would emit an output pulse is up to node implementation as well.
It could pulse on an update from sensor, on SMS received or on timeout event,
for example.
The node's implementation also decides when to emit an output pulse.
For example, a node could pulse when a sensor reading updates, an SMS is
received, or a timeout event occurs.
Some examples of effect nodes are:
@@ -106,109 +105,110 @@ Some examples of effect nodes are:
* [`analog-input`](/libs/xod/core/analog-input/)
* [`pwm-output`](/libs/xod/core/pwm-output/)
Effect nodes is a thing that complements functional land so that your program
could interact with a user, the world, and the time.
Effect nodes complement functional nodes so your program can interact with
users, the world, and time.
Program life cycle
------------------
In any particular moment a XOD program is either in a transaction or in an idle
state.
At any particular moment, a XOD program is either in a transaction or in an
idle state.
While being idle the system stays stable, nothing changes. A board can even
choose to go sleep to keep battery charge longer. What makes the program go out
of idle state is getting a new pulse from an effect node. It could be a pulse
from system clock or a sensor, for example.
While idle, the system remains stable, nothing changes. A board can even
choose to go to sleep to preserve the battery. Receiving a new pulse from an
effect node, e.g. a system clock or sensor, is what makes the program leave the
idle state.
A pulse cause the program to enter a new *transaction*. The pulse flows along
links downstream and cause nodes it hits to update. Node update process is
called *evaluation* in XOD.
A pulse causes the program to enter a new *transaction*. The pulse flows
downstream along links and causes the nodes it hits to update. The process of
updating a node is called *evaluation* in XOD.
At the moment of pulse emission a node can (and in most cases it would) set new
values on its other ouput pins that have value types such as number or boolean.
At the moment a pulse is emitted, a node can (and in most cases does) set new
values on its other ouput pins with value types such as number or boolean.
Evaluation of a node hit by a pulse in most cases would require computing
actual values on other nodes input pins. That values could depend on values of
upstream nodes outputs, which in turn depend on values of their upstream
nodes, and so on. All these dependencies are resolved by the XOD runtime
engine. Final and intermediate values required to evaluate a node are computed
atomically in the transaction.
Evaluation of a node hit by a pulse usually requires computing
actual values on another nodes input pins. The values on these pins could
depend on the values of upstream nodes outputs, which in turn depend on the
values of their upstream nodes, and so on. All these dependencies are resolved
by the XOD runtime engine. The final and intermediate values required to
evaluate a node are computed atomically in the transaction.
After all nodes affected by a pulse are evaluated the transaction completes and
the system returns to the idle state.
After all nodes affected by a pulse are evaluated the transaction is complete
and the system returns to the idle state.
Transaction rules
-----------------
### No external pulses while a transaction is in progress
Any transaction has a guard that will not allow any external pulse to come half
way along the current transaction is in progress. Such pulse will be postponed
and would trigger a new transaction after the current one completes.
All transaction prevent any external pulses from occuring while the current
transaction is in progress. Such a pulse would be postponed and trigger a new
transaction after the current transaction is complete.
To be more precise, external pulses are pushed into a FIFO queue. And once the
system is in the idle state a pulse is popped from the queue and a new
transaction is initiated. The transaction completes, the system goes idle,
takes next pulse from the queue, launches new transaction, and so on until the
queue is empty.
To be more precise, external pulses are pushed into a FIFO queue. Once the
system is idle, a pulse is popped from the queue and a new transaction is
initiated. The transaction completes, the system goes idle, takes the next
pulse from the queue, launches a new transaction, etc. until the queue is
empty.
### Evaluation order
During a transaction any particular node will be evaluated only after all nodes
it depends on via links would be evaluated in their turn.
During a transaction, a node is evaluated only after all nodes
it depends on via links have been evaluated.
Consider following example.
Consider the following example.
![Diamond graph](./abc.patch.png)
The result node will be only evaluated after both branches are evaluated despite
they have node chains of different length. You cant know the order the branches
will be evaluated. It could be M1-M2-M3, M3-M1-M2, M1-M3-M2, or even M1-M2 and
M3 in parallel. Furthermore, result node evaluation could be postponed until
its values would be actually required (so called “lazy evaluation”). Its up to
target platform to decide.
The result node will only be evaluated after both branches are evaluated,
despite the fact that they have node chains of different length. You cant
know the order in which the branches will be evaluated. It could be M1-M2-M3,
M3-M1-M2, M1-M3-M2, or even M1-M2 and M3 in parallel. Furthermore, evaluation
of the result node might be postponed until its values are actually required
(so-called “lazy evaluation”). The target platform decides.
The only thing that does matter is a node will be never evaluated with incomplete
data.
The only thing that does matter is that a node will be never evaluated with
incomplete data.
That is the reason why inputs cant have more than one incoming link. In other
case the ambiguity will take place when two or more links would try to deliver
That is the reason why inputs cant have more than one incoming link.
Otherwise, there would be ambiguity if two or more links tried to deliver
different values.
### Buffering
Effect nodes outputs are *buffered* when changed. In other words the outputs
keep most recent value they got. The data is persistent between transactions. So
a node will “see” the buffered value from an old transaction via link if it is
required to evaluate again due to other input value change.
Effect nodes outputs are *buffered* when changed. In other words, the
outputs keep their most recent value. The data is persistent between
transactions. So a node will “see” the buffered value from an old
transaction via a link if the node must be evaluated again due to a change in
another input's value.
<div class="ui segment">
<span class="ui ribbon label">Pro Tip</span>
If youre familiar with conventional programming think of pins and their
buffered values as <em>variables</em>. They hold the program state and evolve over the
time.
If youre familiar with conventional programming, think of pins and their
buffered values as <em>variables</em>. They hold the program state and evolve
over time.
</div>
Whether values on of functional nodes pins would be buffered is up to target
platform to decide. Since outputs of a functional node depend only on its
inputs the decision is just a matter of execution speed vs RAM consumption. It
The target platform decides whether the values on functional nodes pins will
be buffered. Since a functional node's outputs depend only on its
inputs, the decision is just a matter of execution speed vs RAM consumption. It
has no effect on actual program behavior.
### Feedback loops handling
In XOD link cycles that contain only functional nodes are not allowed. They
would lead to dead locks and program hangs.
In XOD, link cycles that contain only functional nodes are not allowed. They
would lead to deadlocks and hangs.
However it is OK to have a cycle broken by an effect node. In that case
new value will be delivered via feedback link but the node will “see” it
only once it would receive new incoming pulse.
However, cycles broken by effect nodes are OK. In this case, a new value will
be delivered via the feedback link, but the node will “see” it only once it has
received a new incoming pulse.
Summary
-------
Program life cycle can be looked at as a infinite series of transactions that
run whenever an external impact occurs. Pulses drive the program. No pulses, no
changes.
The program's life cycle can be looked at as a infinite series of transactions
that run whenever an external impact occurs. Pulses drive the program. No
pulses, no changes.
Transactions are protected from sudden pulses that could change or make it
ambiguous the order of nodes evaluation.
Transactions are protected from sudden pulses that could change or make
ambiguous the order of node evaluation.

View File

@@ -5,34 +5,34 @@ title: Linking Rules
Linking Rules
=============
To make behavior of XOD programs predictable there are some rules on how pins
can be linked.
To make XOD programs behave predictably, there are some rules on how pins can
be linked.
Outputs and inputs
------------------
Youre are not allowed to link two input pins, neither youre allowed to link
Youre are not allowed to link two input pins, nor are you allowed to link
two output pins. It doesnt makes much sense.
A link should always connect an output and an input.
A link must always connect an output and an input.
If you want to mirror values, just create multiple links from an output pin.
![Link fan out](./fan-out.patch.png)
An output can have an arbitrary number of links and an input can have
no more than one incoming link.
An output can have an arbitrary number of links, but an input can have no more
than one incoming link.
Type matching
-------------
If an input and an output has same [data type](../data-types/) they
may be linked as is.
If an input and an output have the same [data type](../data-types/), they may
be linked as is.
However if they have different types they are only allowed to be linked if
[casting](../data-types/#casting-rules) between their type is possible.
However, if they have different types, they can only be linked if the output
type can be [cast](../data-types/#casting-rules) into the input type.
Once you start linking pins that are suitable for other end of the link
Once you start linking, pins that are suitable for the other end of the link
are highlighted.
Color code

View File

@@ -5,20 +5,20 @@ title: Program Structure
Program Structure
=================
Programs in XOD are quite similar to electronic circuits. Whereas to build an
electronic circuit you use various electronic components and connect them
with wires, in a XOD program you use *nodes* and connect them with *links*.
XOD programs are quite similar to electronic circuits. To build an
electronic circuit, you use various electronic components and connect them
with wires. In a XOD program, you use *nodes* and connect them with *links*.
![Example patch](./example.patch.png)
Nodes
-----
What a node does depends on its type. Like in reality there are ICs to control
motors, amplify audio signals, store data, in XOD there are many types of
nodes available. It is easy to create your own as well.
What a node does depends on its type. Just as there are ICs in the physical
world to control motors, amplify audio signals, and store data, in XOD there
are many types of nodes available. You can also easily create your own.
Some nodes represent physical devices like LED or digital thermometer, other
Some nodes represent physical devices like LEDs or digital thermometers. Others
are used to transform and filter data. Here are few examples:
* [`thermometer-tmp36`](/libs/xod/common-hardware/thermometer-tmp36/)
@@ -26,80 +26,81 @@ are used to transform and filter data. Here are few examples:
* [`add`](/libs/xod/core/add/)
* [`to-percent`](/libs/xod/core/to-percent/)
You place nodes youve chosen for your program into slots to be later connected
with links.
You place the nodes youve chosen for your program into slots to be later
connected with links.
Pins, inputs, and outputs
-------------------------
Nodes alone are black boxes. To interact with them they expose *pins*. Think of
pins as of sockets, ports, IC legs, jack-connectors.
Nodes alone are black boxes. They expose *pins* to support interaction. Think
of pins as of sockets, ports, IC legs, and jacks.
A pin can be either *input* or *output*. Once you feed an input with a new value
the node is evaluated. As a reaction it can update values of its output pins or
perform some interaction with real world, e.g. change a motor speed.
A pin can be either an *input* or an *output*. Once you feed a new value to an
input, the node is evaluated. In response, it may update the values on its
output pins or interact with the real world in some way, e.g. change a motor's
speed.
Some nodes send an output on their own as a reaction to some external event. For
example the [clock](/libs/xod/core/clock/) node sends output with regular time
intervals.
Some nodes send an output on their own as a reaction to some external event.
For example, the [clock](/libs/xod/core/clock/) node sends outputs at regular
time intervals.
Pins are depicted as holes with short labels. Inputs are placed on a darker
background and outputs are placed on a lighter background.
background, and outputs are placed on a lighter background.
![Nodes inputs and outputs](./nodes-inputs-outputs.png)
Links and values
----------------
Nodes talk to each other by transmitting values over *links*. A link is a
kind of wire that you use to connect one node output to another node input.
Nodes talk to each other by transmitting values over *links*. A link is a kind
of wire that you use to connect one node's output to another node's input.
Values in XOD are quite similar to electric signals. However unlike their
electric counterparts they could carry not only a primitive voltage value, but
electric counterparts, they can carry not only raw voltage values, but also
more sensible data like arbitrary numbers and text strings. Learn more about
values in [Data Types](../data-types/) article.
values in the [Data Types](../data-types/) article.
In digital electronics voltage values are switched discretely and their change
usually accompanied by some kind of clock signal. The clock signal is seen as
a sequence of “moments” which are defined by observing falling or rising signal
edges on the clock line. Interactions and changes actually happen at that
moments. I.e. a digital circuit is static until a new clock signal would
appear.
In digital electronics, voltage values are switched discretely, usually
accompanied by some kind of clock signal. The clock signal is seen as a
sequence of “moments” defined by the falling or rising signal edges on the
clock line. Interactions and changes actually happen at these moments, i.e. a
digital circuit is static until a new clock signal appears.
Behavior of values in XOD is very much similar. Values change and propogate
instantly. These cascade updates of values are called *transactions*. And things
that play a role of clock signals are called *pulses* in XOD. [Execution
Model](../execution-model/) article describes all principles in detail.
Values behave very similarly in XOD. They change and propogate
instantly. These cascading value updates are called *transactions*. In XOD, the
role of clock signals is played by *pulses*. The [Execution
Model](../execution-model/) article describes how they work in detail.
There are few rules that define which pins are allowed to be linked and which
are not. They are intuitive enough, although for a formal description you can
see [Linking Rules](../linking-rules/).
There are a few rules that define which pins are allowed to be linked and which
are not. They are intuitive enough, but for a formal description see [Linking
Rules](../linking-rules/).
Patches
-------
Nodes linked together form a *patch*. Patches are like modules, documents, files
in other systems.
Nodes linked together form a *patch*. Patches are like modules, documents, or
files in other programming systems.
You would have a single patch in a simple project and for complex projects youd
likely to have many.
You would have a single patch in a simple project, while youd likely have
many for complex projects.
What makes a patch pretty interesting is that once youve created it you can
use it as a new type of node on other patches! Thats the main idea behind XOD
What makes a patch interesting is that once youve created one you can use it
as a new type of node in other patches! Thats the main idea behind XOD
extensibility.
You use special *terminal nodes* to denote input and output pins when the patch
You use special *terminal nodes* to denote input and output pins when a patch
is used as a node.
<div class="ui segment">
<span class="ui bottom attached label">
Photo by <a href="https://www.flickr.com/photos/26735065@N00/">cutwithflourish</a>.
Photo by
<a href="https://www.flickr.com/photos/26735065@N00/">cutwithflourish</a>.
</span>
<p>
<span class="ui blue ribbon label">Note</span>
If youve heard of modular synthesizers they are very similar to XOD programs.
The nodes are modules, the links are CV cables with banana connectors,
the patches are rack chassis for modules.
Perhaps youve heard of modular synthesizers - they are very similar to XOD
programs. Nodes are modules, links are CV cables with banana connectors,
and patches are a rack chassis for modules.
</p>
<div class="ui fluid image">
<img src="modular-synth.jpg" alt="Modular synth" />

View File

@@ -5,47 +5,46 @@ title: Complex Projects
Complex Projects
================
In past chapters of the tutorial series youve used bare minimum of nodes to
build simple projects. But what if you need to create something more complex?
In the tutorial's past chapters, youve used a bare minimum of nodes to build
simple projects. But what if you need to create something more complex?
The principle of programming will stay the same although you would create
more patches and use more nodes.
The programming principles stay the same even if you create more patches and
use more nodes.
Search for nodes
----------------
Before implementing your own nodes check if there is a ready to use node
that will solve your problem. Visit [library index](/libs/) to browse for
existing nodes.
Before implementing your own nodes, check if there is a ready to use node that
will solve your problem. Visit [library index](/libs/) to browse for existing
nodes.
Interfacing with hardware
-------------------------
If you want to use a sensor or an electronic module that you havent find
support for its quite possible that all you need for it is few standard
nodes like `analog-input` or `digital-output`.
If you want to use a sensor or an electronic module that you havent found
support for, its quite possible that all you need is a few standard nodes
like `analog-input` or `digital-output`.
Refer to the item documentation to understand how you can talk with the
Refer to the item's documentation to understand how you can talk with the
hardware.
Write a native wrapper
----------------------
You can implement a new node not only with XOD, but with C++ as well.
In this case you can even wrap an existing native library to make it
available in XOD.
You can implement new nodes not only in XOD, but also with C++.
You can even wrap an existing native library to make it available in XOD.
See implementation of `analog-input`, `digital-output`, `text-lcd-16x2`
as an example of how to do this.
See the implementation of `analog-input`, `digital-output`, and `text-lcd-16x2`
for examples of how to do this.
Tell us what you need
---------------------
XOD ecosystem is poor since the project is very-very young. If you need
a node for something, [ask for it on our forum](//forum.xod.io). That
would help us to better prioritize our work.
The XOD ecosystem is barebones since the project is very-very young. If you
need a node for something, [ask for it on our forum](//forum.xod.io). That will
help us better prioritize our work.
Dive into details
-----------------
Read [Users guide](/docs/#users-guide) to understand XOD better.
Read the [Users guide](/docs/#users-guide) to understand XOD better.

View File

@@ -1,20 +1,23 @@
---
title: Data Types and Conversions Between Them
title: Data Types and Conversions
---
Data Types and Conversions Between Them
Data Types and Conversions
=======================================
In previous tutorial chapters youve had a deal with pulses and logical values.
In previous tutorial chapters, youve had to deal with pulses and logical
values.
A pulse just denotes the fact something happened and logical values carry
either 0 or 1 value.
The later is called *boolean* data type and its values are called boolean values.
Its just a matter of terminology, but boolean value which corresponds to
1/high/on/enable is called *true*, and 0/low/off/disable value is called *false*.
The latter is called a *boolean* data type, and its values are called boolean
values.
Its just a matter of terminology, but the boolean value that corresponds to
1/high/on/enable is called *true*, and the boolean value corresponding to
0/low/off/disable value is called *false*.
There are more types in XOD to express more than simple flow of boolean values.
Lets get familiar with them.
XOD has other types to express more than a simple flow of boolean values.
Let's get familiar with them.
Number type
-----------
@@ -22,42 +25,45 @@ Number type
42, 3.14159, -2.7… All these are numbers. They can be used to describe values
like temperature, distance, angle, acceleration along an axis, and many more.
Lets use few nodes that employ numbers. We are going to build a simple dimmer
with a potentiometer which would set LED brightness. First of all, we need a
Lets use few nodes that operate on numbers. We are going to build a simple
dimmer with a potentiometer that sets LED brightness. First of all, we need a
circuit:
![Pot and LED circuit](./pot-led.fz.png)
We would like to control LED brightness, so make sure to connect the LED to a
port with PWM feature available. They are marked with tilda (~). And since the
potentiometer provides analog values its port should be capable of reading
analog signals. Ports marked A0 through A5 are good choise for that.
We would like to control LED brightness, so be sure to connect the LED to a
port that supports PWM. They are marked with a tilda (~). Because the
potentiometer provides analog values, its port must be capable of reading
analog signals. Ports marked A0 through A5 are a good choice for that.
Then create new project with main menu: File → New Project. Name it
`pot-led-dimmer` or something like that. Add nodes and links to get a program
that looks like one below:
Then create a new project from the main menu: File → New Project. Name it
`pot-led-dimmer` or something like that. Add nodes and links to create a
program that looks like the one below:
![Pot and LED patch](./pot-led.patch.png)
We use `pwm-output` from `xod/core` to provide PWM signal to our LED.
The `DUTY` input defines duty cycle. Value 0.0 denotes always-low signal
(LED is off), 0.33 is for 33% cycle (third of full brightness), 0.5 is for
50% brightness, etc up to 1.0 for always-high signal when LED is 100% on.
We use `pwm-output` from `xod/core` to provide a PWM signal to our LED. The
`DUTY` input defines the duty cycle. The value 0.0 denotes the always-low
signal (LED is off), 0.33 is for a 33% cycle (one-third of full brightness),
0.5 is for
50% brightness, etc. up to 1.0 for the always-high signal when the LED is 100%
on.
Make sure to set `PORT` input value to 3 with Inspector.
Be sure to set the `PORT` input value to 3 with Inspector.
Next, we use `analog-input` from `xod/core` to read values from potentiometer.
Read values are available on its output `SIG` and take value 0.0 for one edge
point of potentiometer, 1.0 for another, and fractional values for anything
Next we use `analog-input` from `xod/core` to read values from the
potentiometer. Read values are available on its output `SIG` and take the value
0.0 for one of the potentiometer's limits, 1.0 for the other, and fractional
values for anything
between them.
For `PORT` value of `analog-input` use value 14 which corresponds to pin A0
on the board.
For the `PORT` value on the `analog-input`, use value 14 which corresponds to
pin A0 on the board.
<div class="ui segment">
<p>
<span class="ui ribbon label">XOD T0D0</span>
Currently ports are represented as simple numbers. So you cant enter value
Ports are currently represented as simple numbers. So you cant enter a value
like `A0` directly. Just remember that A0 is 14 behind the scenes, A1 is 15,
A2 is 16, etc.
</p>
@@ -65,90 +71,100 @@ A2 is 16, etc.
<p>This inconvenience will be fixed in future versions of XOD.</p>
</div>
We need some source of pulses that would kick `analog-input` to update readings.
Again, `clock` would help. Set its `IVAL` to 0.02 seconds. That would give us
50 Hertz refresh rate.
We need some source of pulses that will kick `analog-input` to update its
readings.
The `clock` node will help here. Set its `IVAL` to 0.02 seconds. That would
give us a 50 Hertz refresh rate.
Now note that we have `SIG` output of our potentiometer linked to `DUTY` input
of our LED. They both operate on *number type* in range from 0.0 to 1.0, so no
Now note that we have the `SIG` output of our potentiometer linked to the
`DUTY` input of our LED. They both operate on a *number type* in the range from
0.0 to 1.0, so no
conversions are necessary and we link them directly.
Finally, our program reads like this:
Our program now runs like this:
- On boot the clock is set up;
- Every 20 ms the clock kicks the analog input with potentiometer causing it
to read value again;
- The value is feed to PWM output with LED causing it to update its brightness.
- On boot, the clock is set up;
- Every 20 ms the clock kicks the analog input with the potentiometer, causing
it to read the value again;
- The value is fed to the PWM output with the LED, causing it to update its
brightness.
Upload the program to your board and checkout the result.
Upload the program to your board and check out the result.
Compare to convert between numbers and booleans
-----------------------------------------------
Lets modify our device a bit so that it would work as a smart light. It should
turn on when its too dark and turn off when its bright enough. For this were
going to replace the potentiometer with simple LDR-based voltage divider:
Lets slightly modify our device to make a smart light. It should turn on
when its too dark and turn off when its bright enough. To do this,
were going to replace the potentiometer with a simple LDR-based voltage
divider:
![LDR and LED circuit](./ldr-led.fz.png)
Now our A0 port provides number values which correspond to ambient light
brightness. We should define a threshold value and if the value is under it, the
LED should be on, otherwise it should be off. So we should map a number value to
a boolean value somehow.
Now our A0 port provides number values that correspond to the brightness of the
ambient light. We should define a threshold value: if the value is under the
threshold, the
LED should be on; otherwise it should be off. So we need to somehow map a
number value to a boolean value.
A common way to do this is using comparison nodes `less`, `greater`, `equal` from
`xod/core`. Lets do it:
This is commonly done using the comparison nodes `less`, `greater`, `equal`
from `xod/core`. Lets do it:
![LDR and LED patch](./ldr-led.patch.png)
The `less` node compares two numbers on left hand side (`LHS`) and right hand side
(`RHS`) and outputs true iff `LHS` < `RHS`. Set `RHS` to a constant value using
Inspector. An exact value depends on characteristics of the resistors and desired
darkness threshold. You could experiment a bit with it. 0.5 could work fine as a
start value.
The `less` node compares the two numbers on the left hand side (`LHS`) and the
right hand side (`RHS`) and outputs true iff `LHS` < `RHS`. Set `RHS` to a
constant value using
Inspector. The exact value depends on characteristics of the resistors and
desired darkness threshold. You could experiment a bit with it. 0.5 should work
fine as a
starting value.
Upload the program. Make sure the LED is off when device starts. If not, adjust the
threshold value. Then cover the LDR with your hand to simulate darkness, the LED
Upload the program. Make sure the LED is off when the device starts. If not,
adjust the threshold value. Then cover the LDR with your hand to simulate
darkness. The LED
should turn on.
Look at the program again. Notice that we dont tell our LED to turn off if
some condition met, then turn off if another computation gave us some value.
Instead we hard-wire pins of our nodes making the behavior explicit and easy
to reason about. Thats what differentiates functional/reactive paradigm of XOD
some condition met and then turn off against based on another computation.
Instead, we hard-wire our node's pins, making the behavior explicit and easy
to understand. Thats what differentiates XOD's functional/reactive paradigm
from conventional programming like C.
String type
-----------
Now you are familiar with pulses, booleans, and numbers. XOD also provides string
type. Strings are used to represent pieces of textual data. They could represent
single or multiple lines, or they could even be empty.
Now you are familiar with pulses, booleans, and numbers. XOD also provides a
string type. Strings are used to represent pieces of textual data. They may
represent single or multiple lines, and can even be empty.
`"Hello world!"` is a string, `""` is an empty string, `"0.42"` is a string too,
although it contains only numeric characters and looks like a number at a first sight.
`"Hello world!"` is a string. `""` is an empty string. `"0.42"` is a string
too, though it contains only numeric characters and looks like a number at a
first sight.
Lets improve our device to show the lightness level on LCD screen. Use any
widespread text LCD to build circuit like one below:
Lets improve our device to show the lightness level on an LCD screen. Use
any popular text LCD to build a circuit like one below:
![LDR, LED, and LCD circuit](./ldr-led-lcd.fz.png)
Add `text-lcd-16x2` node from `xod/common-hardware`. And give it the value of
`analog-input` as an input for the first line (`L1`). Link output of the `less` node
Add the `text-lcd-16x2` node from `xod/common-hardware` and give it the value
of `analog-input` as an input for the first line (`L1`). Link the output of the
`less` node
to the `L2` input.
![LDR, LED, and LCD patch](./ldr-led-lcd.patch.png)
Now upload the program to the board. See how the data is displayed and updated as
you cover the sensor.
Now upload the program to the board. See how the data is displayed and updated
as you cover the sensor.
Note that `L1` and `L2` inputs of the LCD expect string type values. And we linked
number and boolean values to them. This is possible because automatic conversion
from any type to string is possible. Although the inverse isnt true.
Note that the LCD's `L1` and `L2` inputs expect string values, but we linked
number and boolean values to them. This is possible because any type can be
automatically converted to a string. The reverse isnt true.
Whats next
-----------
If youre going to build a project that is more complex than trivial, the program
created on a single pane would be too complicated. There is a mechanism in XOD that
allows you to easily create your own nodes from existing. Learn how to do it
in [Patch Nodes](../patch-nodes/) chapter.
If youre going to build a project that is more complex than trivial, a
program created on a single patch would be too complicated. XOD has a mechanism
that lets you easily create your own nodes from existing nodes. Learn how to do
it in the [Patch Nodes](../patch-nodes/) chapter.

View File

@@ -5,82 +5,85 @@ title: Installing and Running XOD
Installing and Running XOD
==========================
To work with XOD you would use XOD integrated development environment
(IDE for short). It comes in two flavors: browser-based version and
desktop version.
To work with XOD, you use the XOD integrated development environment (IDE for
short), which comes in two flavors: browser-based and desktop version.
Browser-based IDE
-----------------
You can start [browser-based XOD IDE](/ide/) just by visiting the link.
However, since browser has few access permissions to computers file system and
You can start the [browser-based XOD IDE](/ide/) simply by visiting the link.
However, because the browser has relatively few permissions to access the
computers file system and
USB-ports, its capabilities are quite limited.
Notably you cant upload your program directly to the board from within browser
and you wouldnt get convenient save/load functionality.
Notably, you cant upload your program directly to the board from within your
browser and you won't get the convenient save/load functionality.
Although, you can import/export your programs as a single file (so called xodball)
and generate source code that you could copy and paste into Arduino IDE and then
upload it to the board via Arduino IDE.
However, you can import/export your programs as a single file (known as a
xodball), generate source code that you could copy and paste into an Arduino
IDE, and then upload it to the board via the Arduino IDE.
Desktop IDE
-----------
XOD IDE for desktop requires installing but provides all features. It works on
Windows, macOS, and Linux. Find a distributive for your system on
XOD IDE for desktop requires installing, but provides all features. It works on
Windows, macOS, and Linux. Find a distribution package for your system on
[downloads page](/downloads/).
Upload your first program
-------------------------
Once you start XOD IDE youll see `welcome-to-xod` project open. Its a primitive
demo project that—yes, you guess it—blinks a LED on the board.
Once you start XOD IDE, youll see the `welcome-to-xod` project open. Its
a primitive demo project that—yes, you guessed it—blinks a LED on the board.
![XOD main window](./main-window.png)
Lets try to upload the program to your Arduino.
Let's try to upload the program to your Arduino IDE.
In main menu go to Deploy → Show Code for Arduino. Youll see much of C++ source code
that once compiled and uploaded to the board would blink built-in LED. If you have
Arduino IDE installed, try it, copy-paste the code to Arduino IDE and click Upload.
In the main menu, go to Deploy → Show Code for Arduino. Youll see much of
C++ source code that once compiled and uploaded to the board will blink the
built-in LED. If you have the Arduino IDE installed, try it. Copy and paste the
code to the Arduino IDE and click Upload.
<div class="ui segment">
<span class="ui ribbon label">Note</span>
If youve previously seen what code to blink a LED looks like for Arduino, you could
be astonished looking at the amount of code given by XOD. Dont worry, most of it is
a code of XOD runtime environment which actually give little overhead after compilation.
And you havent to understand how it actually works. For now think about it as
of black box.
If youve previously seen what code to blink an LED looks like for Arduino,
you might be astonished looking at the amount of code produced by XOD. Dont
worry - most of it is code for the XOD runtime environment, which actually
creates little overhead after compilation.
You don't need to understand how it actually works. For now, think of it as a
black box.
</div>
Upload directly from within XOD IDE
Upload directly from within the XOD IDE
-----------------------------------
The feature is only available in desktop version. Go to Deploy → Upload to Arduino.
Select your board model and serial port it is connected to:
This feature is only available in the desktop version. Go to Deploy → Upload
to Arduino. Select your board model and the serial port it is connected to:
![XOD model/port dialog](./board-selection.png)
Click Upload. Hold on.
Click Upload and wait.
Behind the scenes XOD uses Arduino IDE to compile and upload programs. So if
you have no Arduino IDE installed yet, youll be asked to download and install
it. Arduino IDE itself has package system to support various boards. If a package
to support your board is not installed yet, it would be automatically installed
as well.
Behind the scenes, XOD uses the Arduino IDE to compile and upload programs. So
if you have no Arduino IDE installed yet, youll be asked to download and
install it. The Arduino IDE itself has a package system to support various
boards. If a package supporting your board is not installed yet, it will also
be automatically installed.
If upload succeeds youll see 100% progress and a message from compiler:
If the upload succeeds, youll see 100% progress and a compiler message:
![XOD upload window](./upload.png)
<Feedback>
If you have a problem with upload, please report about it on our
[forum](//forum.xod.io). Describe what you do, what you expect to get, and
what you actually get. We will help.
</Feedback>
<div class="ui segment">
<span class="ui ribbon label">Feedback</span>
If you have a problem with uploading, please report it on our
[forum](//forum.xod.io). Describe what you're doing, what you expect to get,
and what you actually get. We will help.
</div>
Whats next
-----------
Now, when you can run IDE and upload programs, lets try to understand how and
why they work. Follow to [Nodes and Links](../nodes-and-links/) chapter.
Now that you can run the IDE and upload programs, let's try to understand how
and why they work. Go to the [Nodes and Links](../nodes-and-links/) chapter.

View File

@@ -5,9 +5,9 @@ title: Nodes and Links
Nodes and Links
===============
Now lets look closely on the demo project which opened up on IDE start. It
blinks the LED connected to pin 13 of your board. Although many boards have
a built-in LED on that pin, lets make it more visible by building a simple
Now lets look closely at the demo project that opened up when you started
the IDE. It blinks the LED connected to pin 13 of your board. Many boards have
a built-in LED on that pin, but lets make it more clear by building a simple
circuit:
![LED on pin 13](./led-on-pin-13.fz.png)
@@ -20,9 +20,9 @@ Why does it blink?
The nodes
---------
You see four *nodes* linked together in a chain to make this possible.
Nodes are basic building blocks in XOD. Each of them make a tiny portion
of work and communicate to others.
You see four *nodes* linked together in a chain to implement the blinking.
Nodes are basic building blocks in XOD. Each of them handles a tiny portion of
work and communicates with other nodes.
![Blink patch](./blink.patch.png)
@@ -30,83 +30,84 @@ Lets talk about each node one by one from bottom to top.
### digital-output
This node represents a single physical pin on the board that is used
as an output, and can be either in high (enabled) or low (disabled)
state. We use it to switch our LED on and off.
This node represents a single physical output pin on the board. It can be
either in a high (enabled) or low (disabled) state. We use it to switch our LED
on and off.
The node has three *inputs*. They are `PORT`, `SIG`, and `UPD`.
The `PORT` defines what physical pin corresponds to the node. Select
the node by clicking on it. Youll see *Inspector* sidebar with
properties related to the selected node, i.e. our `digital-output`.
The `PORT` defines what physical pin corresponds to the node. Select the node
by clicking on it. Youll see the *Inspector* sidebar with the properties of
the selected node, i.e. our `digital-output`.
![Inspector](./inspector.png)
Note that `PORT` value is set to 13th pin.
Note that the `PORT` value is set to 13th pin.
Value on `SIG` input defines wether the digital output port should
go high or low state. In Inspector you see its value disabled with
placeholder “linked”. Thats fine because the value is defined by
an upstream node it is linked to. More on that later.
The value on the `SIG` input defines whether the digital output port should go
into a high or low state. In the Inspector, you see its value is disabled and
has the placeholder “linked”. Thats fine, because the value is defined
by a linked upstream node. More on that later.
Input `UPD` listens for *pulses* and used to actually update the signal and
physically update the physical pin according to `SIG` value. In other
words updating `SIG` value alone is not enough and wouldnt lead to any
The `UPD` input listens for *pulses*, uses them to actually update the signal,
and physically updates the physical pin according to the `SIG` value. In other
words, updating the `SIG` value alone is not enough and wouldnt lead to any
visible results.
<div class="ui segment">
<span class="ui ribbon label">Note</span>
<p>Although it could look excessive and strange at first, but <em>any</em> update in
the XOD program is accompanied by pulses. Theyre like heartbeat which delivers
all updates to their destinations. No pulses, no observable effects.</p>
<p>Although it might seem excessive and strange at first, <em>any</em> update
in a XOD program is accompanied by pulses. Theyre like a heartbeat that
delivers all updates to their destinations. No pulses, no observable
effects.</p>
<p>Splitting actual values and pulses helps to understand what and when could
ever happen. That makes programs more explicit and reliable.</p>
<p>Keeping actual values and pulses separate makes it easier to understand what
may happen and when. It makes programs more explicit and reliable.</p>
</div>
Finally, the `digital-output` node listens for pulses on its `UPD` pin and
once it get a pulse, it sets physical port 13 (`PORT`) to a state defined
by a value on the pin `SIG` at the moment when the pulse was recieved.
Finally, the `digital-output` node listens for pulses on its `UPD` pin. Once it
get a pulse, it sets physical port 13 (`PORT`) to a state defined by the value
on the `SIG` pin at the moment when the pulse was received.
### flip-flop
This node is like a virtual light switch that could be turned on (`SET`),
turned off (`RST`) or inverted to an opposite state (`TGL`).
This node is like a virtual light switch that can be turned on (`SET`), turned
off (`RST`) or toggled (`TGL`).
In addition to its inputs the `flip-flop` has two *outputs*. They are
`MEM` which provides current state (high or low) and `CHNG` which sends a
pulse right when value of `MEM` changes.
In addition to its inputs, the `flip-flop` node has two *outputs*. They are
`MEM`, which provides the current state (high or low), and `CHNG`, which sends
a pulse when the value of `MEM` changes.
### clock
The `clock` node emits a pulse on `TICK` output over equal periods of time.
The period is defined by the value of `IVAL` input.
The `clock` node emits a pulse on its `TICK` output at equal time intervals.
The interval is defined by the value of the `IVAL` input.
Select the `clock` node and note the value set for `IVAL` in Inspector.
The interval is set up in seconds.
The interval is expressed in seconds.
The second input `RST` accepts pulses. On pulse the clock accept new interval
value and start counting from scratch.
The second input, `RST`, accepts pulses. On each pulse, the clock accept a new
interval value and starts counting from zero.
Clock is a very usual source of pulses. Youd use it quite often to drive
updates in your programs.
The clock node is a very common source of pulses. Youll use it quite often
to drive updates in your programs.
### boot
The `boot` node is very simple. It sends a single pulse when program starts,
i.e. when the board gets powered on, resetted or reflashed.
The `boot` node is very simple. It sends a single pulse when the program
starts, i.e. when the board gets powered on, reset, or flashed.
<div class="ui segment">
<span class="ui ribbon label">Hint</span>
<p>If pulses are heartbeats, then the clock is a heart. And the boot is a
<p>If pulses are heartbeats, then the clock is a heart. And the boot node is a
defibrillator that starts the clock-heart.</p>
</div>
The links
---------
You see that inputs and outputs of the nodes are connected together with lines.
These lines are called *links* in XOD.
You see that nodes' inputs and outputs are connected together with lines. These
lines are called *links* in XOD.
![Blink patch](./blink.patch.png)
@@ -115,13 +116,13 @@ values and downstream nodes consume that values.
What happens in our blink program? Take a look:
1. The `boot` node emits a pulse on program start
1. The `boot` node emits a pulse when the program starts.
2. The pulse goes to the `clock` node which start to tick at regular intervals
3. Each tick pulse goes to the `flip-flop` and toggles its state
4. The `flip-flop` provides its state value to the `digital-output` and asks
it to actually update by sending a pulse on each state update.
4. The `flip-flop` provides its state value to the `digital-output` and asks it
to update by sending a pulse each time the `flip-flop` changes state.
As a final result we see the LED blinking.
As a result, we see the LED blinking.
Tweaking the program
@@ -129,35 +130,37 @@ Tweaking the program
Try to change something.
Select the `clock` node and set another `IVAL` value. Say, set it to 1.0 seconds,
Select the `clock` node and set a different `IVAL` value, e.g. 1.0 second,
upload the updated program and observe the result.
Thats not too interesting. Lets add another LED. Improve your circuit:
![LED on pin 13 and 12](./led-on-pin-13-and-12.fz.png)
Place new node of type `digital-output`. To do this use Project Browser sidebar.
The `digital-output` is available in `xod/core` library. Hover the cursor over
the item and click on (+).
Place a new `digital-output` node. To do this, use the Project Browser sidebar.
The `digital-output` node is available in the `xod/core` library. Hover the
cursor over the item and click the (+).
![Project Browser](./project-browser.png)
Youll see new node appeared in the main work area. Drag it to a slot you want.
The one next to existing `digital-output` would be fine. In Inspector set `PORT`
for the new node to 12 since it should control our new LED.
Youll see a new node appear in the main workspace. Drag it to the slot you
want. The one next to the existing `digital-output` would be fine. In
Inspector, set the `PORT` for the new node to 12, since it will control our new
LED.
Now we need to provide the new node with data. Link its `SIG` and `UPD` pins to
`flip-flop` outputs:
the `flip-flop` outputs:
![Blink two LEDs](./blink-two-leds.patch.png)
Upload the updated program to the board. Whoa! Both LEDs are blinking.
Now lets improve our program another bit and make the lights opposite. To do
this we should cut signal inversion into either of `digital-output` `SIG` links.
Node `not` under `xod/core` does exactly that. Delete existing link, place `not`
node and add new links so that signal from our `flip-flop` to `digital-output`
goes through it:
Now lets improve our program some more and make the lights blink
alternately. To do this, we need to add a signal inversion into either the
`digital-output` or `SIG` links.
The `not` node under `xod/core` does exactly that. Delete the existing link,
place a `not` node, and add new links so that the signal from our `flip-flop`
to the `digital-output` goes through it:
![Blink two LEDs with inversion](./blink-two-leds-inv.patch.png)
@@ -166,21 +169,22 @@ Upload the new version to the board. See the result?
Disjoint graphs and independent tasks
-------------------------------------
In XOD nodes are not required to be connected in a single network. You can build
In XOD, nodes do not have to be connected in a single circuit. You can build
two or more disjoint clusters of nodes to perform several tasks simultaneously.
Try to add yet another LED with absolutely independent blink interval and state:
Try adding yet another LED with an absolutely independent blink interval and
state:
![Blink with disjoint clusters](./blink-disjoint.patch.png)
Now we have three `digital-output`s. It could be hard to understand which one
corresponds to what LED so it would be better to give them clear labels. To set
a custom label for a node select it and provide the label via Inspector:
Now we have three `digital-output` nodes. It can be hard to understand which
node corresponds to each LED, so it would be better to give them clear labels.
To set
a custom label for a node, select it and provide the label via Inspector:
![Edit label with Inspector](./inspector-label.png)
You can provide a custom label for any node. Now the program could look more
clear:
You can provide a custom label for any node. Now the program looks clearer:
![Labeled nodes](./blink-disjoint-labeled.patch.png)
@@ -189,5 +193,6 @@ Whats next
Youve seen pins and links that carry values of different types. Some provide
logical values and some transmit pulses. They are differentiated by colors.
There are more data types in XOD. Follow to [Types and
Conversions](../data-types-and-conversions/) chapter to learn more on this topic.
XOD has even more data types. Go to the [Types and
Conversions](../data-types-and-conversions/) chapter to learn more on this
topic.

View File

@@ -5,109 +5,114 @@ title: Patch Nodes
Patch Nodes
===========
What you see in a tab of main work area is called a *patch*. In other
programming languages a XOD patch corresponds to a single source file or
module.
What you see on the tab in the main workspace is called a *patch*. A XOD patch
corresponds to a single source file or module in other programming languages.
Until now youve created single-patch programs and the patch was given name
`main` automatically for you. Creating a whole project on a single patch would
become messy once number of nodes and links will pass some limit. In many cases
it is a good idea to split complex patches into several that are easier to
understand and change.
Until now, youve created single-patch programs and the patch was
automatically named `main`. Creating a whole project in a single patch would
become messy once the number of nodes and links passed some limit. It is often
a good idea to split complex patches into several simpler patches that are
easier to understand and edit.
Furthermore, you can reuse a patch several times in your project with slightly
different parameters and in such way avoid nodes duplication.
Furthermore, you can reuse patches several times in your project with slightly
different parameters, thus avoiding node duplication.
The mechanism which lets you use one patches as nodes on other patches is
called *patch nodes*.
When you use one patch as a node in other patches it is called a *patch node*.
In this chapter were going to build simple watering station for two plants.
The idea is to water a plat if its soil became too dry and constantly show current
soil measurements on text LCD screen.
In this chapter, were going to build a simple watering station for two
plants. The idea is to water a plant if its soil became too dry and constantly
show the current
soil measurements on an LCD screen.
Single plant station on a single patch
--------------------------------------
To start lets build a device that will work with a single plant. Well use single
patch `main` as in previous chapters.
To start, let's build a device that will work with a single plant. Well use
a single patch called `main`, as in previous chapters.
Create new project `water-station` and wire up your circuit:
Create a new project called `water-station` and wire up your circuit:
![Single plant circuit](./single-plant.fz.png)
Now make a following patch to control the device:
Now make the following patch to control the device:
![Single plant patch](./single-plant.patch.png)
Make sure to properly set port values for all hardware nodes.
Be sure to set port values properly for all hardware nodes.
You may noticed it is very similar to previously implemented smart light project.
All things weve changed is the sensor and the actuator. Moisture sensor replaced
the light sensor and the pump replaced the LED.
You may have noticed it is very similar to the previously implemented smart
light project. We've only changed the sensor and the actuator. The moisture
sensor replaced the light sensor, and the pump replaced the LED.
Upload the program to your board and test the device. Put the sensor into a glass
of water and take it out. See how the relay reacts. Observe the text shown on LCD.
Upload the program to your board and test the device. Put the sensor into a
glass of water and take it out. See how the relay reacts. Observe the text
shown on the LCD.
Lets improve the program a bit and add pretty formatting to the messages. So that
instead of `"0.42"` the LCD would show something like `"Cactus: 42%"`. We achieve
this by adding two nodes. First one `to-percent` would convert number from sensor
to a string like `"42%"`. Second one `concat` would concatenate a constant prefix
`"Cactus: "` with the percent string:
Lets improve the program a bit by adding pretty formatting to the messages
so that instead of `"0.42"`, the LCD would show something like `"Cactus: 42%"`.
We achieve this by adding two nodes. First, a `to-percent` node will convert a
number from the sensor to a string like `"42%"`. Second, the `concat` node will
concatenate the constant prefix `"Cactus: "` with the percent string:
![Single plant patch with percents](./single-plant-percent.patch.png)
Extracting plant logic to a separate patch
------------------------------------------
So far, so good. Now consider we want to extend the device to handle two plants
at once. We have another sensor, yet another relay, and pump. What we want to
share is LCD. Each plants message should be shown on its own line.
So far, so good. Now consider that we want to extend the device to handle two
plants at once. We have another sensor, yet another relay, and a pump. What we
want to
share is the LCD. Each plants message should be shown on its own line.
The very staightforward way to do it would be duplicate most of nodes related to
reading data, comparing it and formatting the result. But it would quickly became
unmanagable and error prone. Changes in one place would always require mirroring
the changes in other places by hand.
The very staightforward way to do it would be to duplicate most of nodes
related to reading and comparing data, and formatting the result. But it would
quickly become unmanagable and error prone. Changes in one place would always
require manually mirroring those changes in other places.
Patch nodes to the rescue. What do we have in common between different plants and
what differs? The logic is common, but the name of the plant, its watering threshold
value differs. Ports used to connect the sensor and the relay differs too. So
these things should be provided as parameters to our patch.
Patch nodes to the rescue. What do the different plants have in common? And
what is different? The logic is common, but the name of the plant and its
watering threshold value differ. The ports used to connect the sensor and the
relay are also different. So these things need to be provided as parameters to
our patch.
What the patch could output to the outside world? It could be a status message
string and a pulse that denotes that update is completed.
What might the patch output to the outside world? It could be a status message
string and a pulse that denotes that an update is complete.
Create new patch with File → New Patch and name it `plant`. Look at Project Browser
youll see that `plant` patch has appeared next to our `main`.
Create a new patch with File → New Patch, and name it `plant`. Look at
Project Browser. Youll see that a `plant` patch has appeared next to our
`main`.
First of all were going to define its inputs and outputs. Expand
First of all, were going to define its inputs and outputs. Expand
`xod/patch-nodes` in Project Browser and notice nodes with names like
`input-xxx` and `output-xxx`. They are called *terminals* and define patch
input and output pins. Place few inputs and outputs according to what weve
`input-xxx` and `output-xxx`. They are called *terminals*, and define the
patch's
input and output pins. Place a few inputs and outputs according to what weve
planned to parametrize:
![Plant patch terminals](./plant-terminals.patch.png)
Now give the terminal nodes informative labels so that we can remember which one means
what:
Now give the terminal nodes informative labels so we can remember which one
means what:
![Plant patch terminals with labels](./plant-terminals-labeled.patch.png)
Switch back to the `main` patch. And try to add two nodes of our newly created type
`plant`:
Switch back to the `main` patch and try to add two nodes of our newly created
type `plant`:
![Patch nodes](./single-plant-with-patch-nodes.patch.png)
Were going to use these two nodes to manage plants and move existing logic to the
shared `plant` patch. Lets do it.
Were going to use these two nodes to manage plants and move the existing
logic to the shared `plant` patch. Lets do it.
<div class="ui segment">
<p><span class="ui ribbon label">XOD T0D0</span>
Currently there is no cut/copy/paste in XOD. Yes, thats a pain. Well implement it
in future versions. If you would like to give the feature more priority we welcome you to
<a href="//forum.xod.io">share your opinion on our forum</a>.</p>
Currently there is no cut/copy/paste in XOD. Yes, thats a pain. Well
implement it in future versions. If you would like to give the feature more
priority, we welcome you to <a href="//forum.xod.io">share your opinion on our
forum</a>.</p>
</div>
Here is final `main` patch:
Here is the final `main` patch:
![Main patch for two plants](./two-plants-main.patch.png)
@@ -119,12 +124,12 @@ Wire up the circuit:
![Single plant circuit](./two-plants.fz.png)
Set parameters for your plants with Inspector. Then upload the program and see how
both plants are served simultaneously with a single patch.
Set parameters for your plants with Inspector. Then upload the program and see
how both plants are served simultaneously with a single patch.
Whats next
-----------
Our quick tutorial is almost completed. The last thing to learn is what you can do
to build arbitrary projects with arbitrary hardware.
See [Complex Projects](../complex-projects/) chapter to know more.
Our quick tutorial is almost complete. The last thing to learn is what you can
do to build arbitrary projects with arbitrary hardware. See the [Complex
Projects](../complex-projects/) chapter to learn more.