doc/manual: more tutorial steps

This commit is contained in:
Sebastien Bourdeauducq 2014-09-29 20:20:14 +08:00
parent 1ae7724a15
commit 6a1cf8749d
1 changed files with 53 additions and 4 deletions

View File

@ -34,8 +34,8 @@ The LED of the device should turn on. Congratulations! You have a basic ARTIQ sy
.. note::
ARTIQ requires Python 3, and you may need to use the ``python3`` command instead of ``python`` on some distributions.
Interaction with the host
-------------------------
Host/core device interaction
----------------------------
A method or function running on the core device (which we call a "kernel") may communicate with the host by calling non-kernel functions that may accept parameters and may return a value. The "remote procedure call" (RPC) mechanisms handle automatically the communication between the host and the device of which function to call, with which parameters, and what the returned value is.
@ -100,6 +100,55 @@ Create a new file ``rtio.py`` containing the following: ::
exp = Tutorial(core=core_driver, o=out_driver)
exp.run()
Connect an oscilloscope to the RTIO channel 1 (pin C11 on the Papilio Pro) and run ``python rtio.py``. Notice that the generated signal's period is precisely 4 microseconds, and that it has a duty cycle of precisely 50%. This is not what you would expect if the delay and the pulse were implemented with CPU-controlled GPIO: overhead from the loop management, function calls, etc. would increase the signal's period, and asymmetry in the overhead would cause duty cycle distortion.
Connect an oscilloscope or logic analyzer to the RTIO channel 1 (pin C11 on the Papilio Pro) and run ``python rtio.py``. Notice that the generated signal's period is precisely 4 microseconds, and that it has a duty cycle of precisely 50%. This is not what you would expect if the delay and the pulse were implemented with CPU-controlled GPIO: overhead from the loop management, function calls, etc. would increase the signal's period, and asymmetry in the overhead would cause duty cycle distortion.
Instead, inside the core device, output timing is generated by the gateware and the CPU only programs switching commands with certain timestamps that the CPU computes.
Instead, inside the core device, output timing is generated by the gateware and the CPU only programs switching commands with certain timestamps that the CPU computes. This guarantees precise timing as long as the CPU can keep generating timestamps that are increasing fast enough. In case it fails to do that (and attempts to program an event with a timestamp in the past), the :class:`artiq.devices.runtime_exceptions.RTIOUnderflow` exception is raised. The kernel causing it may catch it (using a regular ``try... except...`` construct), or it will be propagated to the host.
Try reducing the period of the generated waveform until the CPU cannot keep up with the generation of switching events and the underflow exception is raised. Then try catching it: ::
from artiq.devices.runtime_exceptions import RTIOUnderflow
def print_underflow():
print("RTIO underflow occured")
class Tutorial(AutoContext):
parameters = "led o"
def run(self):
self.led.set(0)
try:
for i in range(1000000):
self.o.pulse(...)
delay(...)
except RTIOUnderflow:
self.led.set(1)
print_underflow()
Parallel and sequential blocks
------------------------------
It is often necessary that several pulses overlap one another. This can be expressed through the use of ``with parallel`` constructs, in which all statements execute at the same time. The execution time of the ``parallel`` block is the execution time of its longest statement.
Try the following code and observe the generated pulses on a 2-channel oscilloscope or logic analyzer: ::
for i in range(1000000):
with parallel:
self.o1.pulse(2*us)
self.o2.pulse(4*us)
delay(4*us)
If you assign ``o2`` to the RTIO channel 2, the signal will be generated on the pin C10 of the Papilio Pro.
Within a parallel block, some statements can be made sequential again using a ``with sequential`` construct. Observe the pulses generated by this code: ::
for i in range(1000000):
with parallel:
with sequential:
self.o1.pulse(2*us)
delay(1*us)
self.o1.pulse(1*us)
self.o2.pulse(4*us)
delay(4*us)
.. warning::
In its current implementation, ARTIQ only supports those pulse sequences that can be interleaved at compile time into a sequential series of on/off events. Combinations of ``parallel``/``sequential`` blocks that require multithreading (due to the parallel execution of long loops, complex algorithms, or algorithms that depend on external input) will cause the compiler to return an error.