Commit e8f7b8fb authored by Federico Vaga's avatar Federico Vaga

Merge remote-tracking branch 'origin/proposed_master' into proposed_master

parents 7f49095a 71657cc9
......@@ -34,7 +34,7 @@ Input Events can be either a :ref:`local_channel`, an inbound network :ref:`mess
Output Events can be either a :ref:`local_channel`, or an outbound network :ref:`message`.
An Event is essentially a combination of an :ref:`event_id` (the "what") and a :ref:`timestamp` (the
An Event is essentially a combination of an :ref:`event_id` (the "what") and an :ref:`timestamp` (the
"when").
.. _event_id:
......@@ -113,14 +113,13 @@ Local Channels represent the connections of a :ref:`node` to its environment. Th
inputs or outputs.
A Local Channel input delivers input Events to the :ref:`node`. Typical examples include the
external trigger output of a digitiser, a Time to Digital Converter (TDC) or a TTL input channel on
external trigger input of a digitiser, a Time to Digital Converter (TDC) or a TTL input channel on
a digital I/O board.
A Local Channel output receives output Events from the :ref:`node`. Typical examples include the
external trigger input of a digitiser, a Fine Delay generator or a TTL output channel on a digital
I/O board.
A Local Channel output transmits output Events from the :ref:`node`. Typical examples include a Fine
Delay generator or a TTL output channel on a digital I/O board.
All Local Channels use reserved :ref:`Event IDs <event_id>`.
All Local Channels use specific IDs as described in :ref:`Event IDs <event_id>`.
.. _message:
......@@ -148,12 +147,12 @@ Each Message is transmitted as a single Ethernet frame, with a UDP header and a
The contents of a WRTD Event Message are again based on LXI Event Messages, with the "Domain" and
"Flag" fields (octets 3 and 36 respectively) fixed to zero.
Each Message contains an :ref:`event_id`, a :ref:`timestamp` and a sequence number. The latter is a
Each Message contains an :ref:`event_id`, an :ref:`timestamp` and a sequence number. The latter is a
counter that gets increased by one every time a new Event is generated.
.. hint:: The sequence counter can be used to detect lost or duplicate Messages.
.. hint:: Altough there are currently no "Data Fields" defined (octets 37 and beyond), it should be
.. hint:: Although there are currently no "Data Fields" defined (octets 37 and beyond), it should be
highlighted that the LXI Event message format supports an arbitrary number of data fields, in the
form of Type/Length/Value (TLV) triplets, which could be used to provide additional functionality
to WRTD in the future.
......@@ -218,8 +217,8 @@ Attributes can be attached to a :ref:`rep_cap`, or they can be "global" (apply t
:ref:`node`).
.. note:: Since global Attributes are not attached to any :ref:`rep_cap`, when using one of the
functions to get/set a global Attribute, a special :ref:`rep_cap_id` must be passed to the
function (:c:macro:`WRTD_GLOBAL_REP_CAP_ID`) as the Selector.
functions to get/set a global Attribute, a special :ref:`rep_cap_id`
(:c:macro:`WRTD_GLOBAL_REP_CAP_ID`) must be passed to the function as the Selector.
Please refer to the :ref:`api_attr` for more details.
......
......@@ -9,15 +9,24 @@ This section provides guidelines on how to develop a new WRTD Node (or, modify a
provided by the `WRTD project <https://www.ohwr.org/project/wrtd/>`_. If you simply need to control
an existing WRTD Node, please refer to :numref:`usage` instead.
It should be noted that a new Node need not necessarily use the resources provided by the WRTD
project itself. In fact, the only hard requirement is that the Node is able to send and/or receive
:ref:`Event Messages <message>` over an Ethernet-based LAN.
It should be noted that a new Node does not necessarily need to use the resources provided by the
WRTD project itself. In fact, the only hard requirement is that the Node must be able to send and/or
receive :ref:`Event Messages <message>` over an Ethernet-based LAN, using multicast UDP on address
``224.0.23.159``, port ``5044``. It should also respect the :ref:`event_id` naming conventions of
WRTD.
Of course, the above is the absolute minimum requirement, which is already fullfilled by any LXI
device supporting the relevant LXI extended functions (see also :ref:`lxi`).
Moving one step further, the network interface of the Node should be White Rabbit enabled, to allow
for accurate timestamping and sub-ns synchronisation between the Nodes.
for accurate timestamping and sub-ns synchronisation between the Nodes. This has implications for
your :ref:`hw_dev`.
If your :ref:`node` contains an FPGA and you choose to use the WRTD-provided :ref:`gw_dev`
resources, then this also opens up the possibility of using the WRTD-provided :ref:`fw_dev`
resources as well, to develop the application(s) running inside the FPGA. A WRTD :ref:`node`
developed with the WRTD :ref:`gw_dev` and :ref:`fw_dev` resources will be accessible via the
provided :ref:`clib`, :ref:`pywrap` and :ref:`tools`.
.. _dev_setup:
......@@ -107,11 +116,12 @@ Other than that, the only requirement on the hardware is that it supports `White
<https://www.ohwr.org/project/white-rabbit>`_.
If you are designing your own board and you would like to have something as a reference, here's a
few open-source boards that already support WR:
page which can `help you <https://www.ohwr.org/project/white-rabbit/wikis/WRReferenceDesign>`_, or,
more specifically, here's a list with a few open-source boards that already support WR:
* `SPEC <https://www.ohwr.org/projects/spec>`_ (Xilinx Spartan6 FPGA)
* `FASEC <https://www.ohwr.org/projects/fasec>`_ (Xilinx Zynq SoC FPGA)
* `VFC-HD <https://www.ohwr.org/projects/vfc-hd>`_ (Intel Arria V)
* `SPEC <https://www.ohwr.org/projects/spec/wikis>`_ (Xilinx Spartan6 FPGA)
* `FASEC <https://www.ohwr.org/projects/fasec/wikis>`_ (Xilinx Zynq SoC FPGA)
* `VFC-HD <https://www.ohwr.org/projects/vfc-hd/wikis>`_ (Intel Arria V)
All of the above examples make use of the `WR PTP Core
<https://www.ohwr.org/project/wr-cores/wikis/wrpc-core>`_ inside their FPGA.
......@@ -121,7 +131,178 @@ All of the above examples make use of the `WR PTP Core
Gateware
========
There is no HDL template yet for WRTD gareware development. Users who need to develop WRTD gateware
for a new :ref:`node` are advised to use the top-level VHDL modules of the :ref:`ref_nodes` as a
starting point. Their source code is available on the WRTD Git repository:
https://www.ohwr.org/project/wrtd/tree/master/hdl/top
Every :ref:`node` should include at a minimum an instance of `MockTurtle
<https://www.ohwr.org/project/mock-turtle/wikis/home>`_ and the `WR PTP Core
<https://www.ohwr.org/project/wr-cores/wikis/wrpc-core>`_.
Furthermore, the MockTurtle configuration should define at least one *Host Message Queue* per CPU,
for communication between the WRTD library and the WRTD :ref:`application` running on the CPU, as
well as one *Remote Message Queue* per CPU for conencting the WRTD :ref:`application` to the WR
network.
Every :ref:`node` should also include a *MockTurtle Ethernet Endpoint*, to interface the *Remote
Message Queue* of the MockTurtle with the *Fabric Interface* of the WR PTP Core. If in doubt, have a
look at how these three modules are instantiated and connected to each other in the
:ref:`ref_nodes`.
.. _fw_dev:
Firmware
========
WRTD provides a common firmware development framework for :ref:`Applications <application>`. To use
it, users must also use a compatible :ref:`gw_dev`.
Similar to :ref:`gw_dev` development, users are advised to use the firmware of the :ref:`ref_nodes`
as a starting point:
https://www.ohwr.org/project/wrtd/tree/master/software/firmware
Setup
-----
To start developing firmware for WRTD, users must first include the relevant header file:
.. code-block:: c
#include "wrtd-rt-common.h"
Users must also describe the various features of their application, by means of C preprocessor
directives. The following needs to be copied to the application source code and adjusted as
necessary:
.. code-block:: c
/* Number of MockTurtle CPUs. */
#define NBR_CPUS xxx
/* Index of this CPU. */
#define CPU_IDX xxx
/* Maximum number of Rules allowed */
#define NBR_RULES xxx
/* Maximum number of Alarms allowed */
#define NBR_ALARMS xxx
/* Number of Devices. A "Device" is a unidirectional set
of Local Channels.
Most Applications will have one Device per direction (in/out).
Maximum allowed number of Devices = 4. */
#define NBR_DEVICES xxx
/* Number of Local Channels per Device. */
#define DEVICES_NBR_CHS { xxx, 0, 0, 0}
/* Direction of Local Channels per Device. Direction can be either
WRTD_CH_DIR_IN (from the environment to WRTD) or
WRTD_CH_DIR_OUT (from WRTD to the environment). */
#define DEVICES_CHS_DIR { WRTD_CH_DIR_IN, 0, 0, 0}
/* A unique number to identify this Application. */
#define APP_ID xxx
/* Application version (major, minor). */
#define APP_VER RT_VERSION(xxx, yyy)
/* A string name for this Application. */
#define APP_NAME xxx
/* 1 if the Application can receive Events over the network,
0 otherwise. */
#define WRTD_NET_RX x
/* 1 if the Application can send Events over the network,
0 otherwise. */
#define WRTD_NET_TX x
/* 1 if the Application can receive Events from Local Channels,
0 otherwise. */
#define WRTD_LOCAL_RX x
/* 1 if the Application can send Events to Local Channels,
0 otherwise. */
#define WRTD_LOCAL_TX x
Apart from the preprocessor definitions, users must also provide implementations for a set of
functions. These include:
* :ref:`fw_api_init`
+ :cpp:func:`wrtd_user_init`
+ :cpp:func:`wrtd_io`
* :ref:`fw_api_wr_link`
+ :cpp:func:`wr_link_up`
+ :cpp:func:`wr_time_ready`
+ :cpp:func:`wr_enable_lock`
+ :cpp:func:`wr_time_locked`
+ :cpp:func:`wr_sync_timeout`
* :ref:`fw_api_event_in`
+ :cpp:func:`wrtd_local_output`
.. _fw_api_init:
Initialisation and Main Loop
----------------------------
WRTD firmware runs in a continuous loop. All such code should be put in the :cpp:func:`wrtd_io`
function. Additionally, the :cpp:func:`wrtd_user_init` offers the possibility to execute code once,
after reset, before entering the main execution loop.
.. doxygenfunction:: wrtd_user_init
.. doxygenfunction:: wrtd_io
.. _fw_api_wr_link:
WR Link Control and Status
--------------------------
It is expected (but not required) that WRTD firmware has access to the WR link. In particular, most
applications should be able to detect whether the link is up, the timecode is valid, etc. The way
this is done is application-specific. The following functions allow users to describe how this is
done.
.. doxygenfunction:: wr_link_up
.. doxygenfunction:: wr_time_ready
.. doxygenfunction:: wr_enable_lock
.. doxygenfunction:: wr_time_locked
.. doxygenfunction:: wr_sync_timeout
Event I/O
---------
Ultimately, the purpose of a WRTD firmware is to relay :ref:`Events <event>` from/to the outside
world.
Internally, WRTD represents an Event using the :cpp:class:`wrtd_event` structure.
.. doxygenstruct:: wrtd_event
:members:
.. _fw_api_event_in:
Sending Events
++++++++++++++
When an incoming :ref:`Event <event>` has been matched to a :ref:`rule` with a :ref:`local_channel`
output, WRTD will call the user-provided :cpp:func:`wrtd_local_output` function. This function
should perform all the application-specific actions to program the relevant :ref:`local_channel` to
generate the actual output.
.. doxygenfunction:: wrtd_local_output
.. _fw_api_event_out:
Receiving Events
++++++++++++++++
Receiving an :ref:`event` is also application-specific. The monitoring of :ref:`local_channel`
inputs is typically done periodically in the main execution loop, using the :cpp:func:`wrtd_io`
function.
Once the firmware detects in incoming :ref:`event` and fills in a :cpp:class:`wrtd_event` structure,
it should simply pass this to WRTD using the :cpp:func:`wrtd_route_in` function. The rest (rule
matching, event forwarding, etc.) will be handled by WRTD.
.. doxygenfunction:: wrtd_route_in
.. hint:: Contrary to the rest of the functions presented in :numref:`fw_dev`,
:cpp:func:`wrtd_route_in` is not a user-defined function. It is provided by WRTD. Users
should simply call this function whenever an incoming :ref:`event` is detected.
......@@ -10,6 +10,9 @@ OPTIMIZE_OUTPUT_FOR_C = YES
EXTRACT_STATIC = YES
CASE_SENSE_NAMES = YES
ENABLE_PREPROCESSING = YES
PREDEFINED = WRTD_NET_RX
WARN_NO_PARAMDOC = YES
WARN_IF_UNDOCUMENTED = NO
......
<mxfile modified="2019-07-19T11:30:00.330Z" host="www.draw.io" agent="Mozilla/5.0 (X11; Linux x86_64; rv:60.0) Gecko/20100101 Firefox/60.0" etag="dVAsjTgn41owFf55ERsg" version="11.0.0" type="device"><diagram id="YKdj9BhTBNf1aPVHSjrr" name="Page-1">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</diagram></mxfile>
\ No newline at end of file
.. _introduction:
ssh://git@ohwr.org:7999/project/wrtd.git.. _introduction:
------------
Introduction
......@@ -9,7 +9,7 @@ over a White Rabbit (WR) network.
As can be seen in :numref:`fig-wrtd-overview`, WRTD Nodes receive "input" Events and distribute them
to other Nodes over WR in the form of network Messages that are used to transfer the Timestamp of
the input Event. The receiving Nodes are programmed to execute some "output Event (action) upon
the input Event. The receiving Nodes are programmed to execute some "output" Event (action) upon
reception of a particular Message, potentially with some fixed delay added to the Timestamp.
.. figure:: graphics/wrtd_overview.png
......@@ -30,7 +30,7 @@ There are two main categories of WRTD applications:
synchronisation provided by WR).
#. The receiving Nodes are "recording" devices (e.g. digitisers), capable of storing data in a
recording buffer. Te source Node transmits the Message, with or without a fixed delay. When one
recording buffer. The source Node transmits the Message, with or without a fixed delay. When one
of the destination Nodes receives the Message, it stops recording and rolls-back its buffer to
the moment specified by the Timestamp in the received Message (provided that it has a large
enough buffer to compensate for the latency). Thus, all Nodes will deliver recorded data from the
......@@ -64,7 +64,7 @@ Relation to IVI and LXI
`LAN eXtensions for Instrumentation (LXI) <http://www.lxistandard.org>`_ is a standard, defining a
communication protocol for the remote control of instrumentation over an Ethernet-based LAN.
Version 1.5 of the LXI splits the specification in two parts:
Version 1.5 of the LXI standard splits the specification in two parts:
#. The `LXI Core Specification`_, to which all LXI Devices must conform.
......@@ -80,7 +80,7 @@ exchange of real-time event messages between instruments. These include:
The core specification requires (Rule 6.1) that all LXI devices provide an `Interchangeable Virtual
Instruments (IVI) <http://ivifoundation.org/>`_ driver. Furthermore, it requires (Rule 6.1.1) that
all LXI devices supporting the exchnage of event messages, do so by providing an API that conforms
all LXI devices supporting the exchange of event messages, do so by providing an API that conforms
to the `IVI-3.15 IviLxiSync Specification`_.
Since the LXI event exchanging mechanism is conceptually very close to WRTD, it was decided to
......@@ -95,7 +95,7 @@ design WRTD to be as close to LXI as possible. In particular:
.. hint:: Do not worry if you do not understand some of the terminology yet. It will be explained in
:numref:`basic_concepts`.
In the future, and with `White Rabbit being standardized within the next release of IEEE-1588
In the future, and with `White Rabbit being standardised within the next release of IEEE-1588
<https://www.ohwr.org/project/wr-std/wikis/home>`_, it is foreseen to try to merge WRTD with
IVI/LXI. A possible way to do this would be to add a new IVI specification, similar to IVI-3.15,
describing the API to control WRTD-enabled devices. This API would be an extension, allowing any
......@@ -112,8 +112,9 @@ order).
(:numref:`hw_dev`), gateware (:numref:`gw_dev`) and firmware (:numref:`fw_dev`).
* Before you embark however on a new design, please have a look first at the existing reference
designs. :numref:`ref_nodes` presents the currently available reference WRTD Nodes that come
pre-programmed with their gateware and firmware.
designs; it could be that one of them is appropriate for your task. :numref:`ref_nodes` presents
the currently available reference WRTD Nodes that come pre-programmed with their gateware and
firmware.
* Whether you develop your own Node or use one of the reference Nodes, :numref:`usage` describes how
to access and control your Node. :numref:`clib` provides all the details on how to use the C
......
......@@ -4,28 +4,17 @@
Reference Nodes
---------------
.. _spec150t_ref_adc:
WRTD provides so-called "reference" :ref:`Nodes <node>` for the most common use-cases.
SPEC150T-based FMC-ADC
======================
Currently these include:
.. figure:: graphics/wrtd_ref_design_spec_adc.png
:name: fig-ref_spec_adc
:align: center
:alt: alternate text
:figclass: align-center
#. :ref:`spec150t_ref_adc`: A four channel, 100MHz, 14bit PCIe-based ADC capable of triggering via
WRTD.
#. :ref:`svec_ref_tdc_fd`: A pulse-in/pulse-out WRTD Node in VME format, for generic trigger
distribution applications.
SPEC150T-based FMC-ADC reference WRTD Node
.. toctree::
:hidden:
.. _svec_ref_tdc_fd:
SVEC-based TDC+FDELAY
=====================
.. figure:: graphics/wrtd_ref_design_svec_list.png
:name: fig-ref_svec_list
:align: center
:alt: alternate text
:figclass: align-center
SVEC-based TDC+FDELAY reference WRTD Node
ref_spec_fmc_adc
ref_svec_tdc_fd
.. _spec150t_ref_adc:
SPEC150T-based FMC-ADC
======================
+----------------------------------------+------------+
| **Parameter** | **Value** |
+========================================+============+
| # of :ref:`Applications <application>` | 1 |
+----------------------------------------+------------+
| Name | wrtd-adc |
+----------------------------------------+------------+
| Local input Channels | 5 |
+----------------------------------------+------------+
| Local output Channels | 1 |
+----------------------------------------+------------+
| Maximum :ref:`Rules <rule>` | 16 |
+----------------------------------------+------------+
| Maximum :ref:`Alarms <alarm>` | 1 |
+----------------------------------------+------------+
| Average input to Message latency | 10μs (TBC) |
+----------------------------------------+------------+
| Average Message to output latency | 10μs (TBC) |
+----------------------------------------+------------+
| Can receive Messages over WR | YES |
+----------------------------------------+------------+
| Can send Messages over WR | YES |
+----------------------------------------+------------+
This is a WRTD :ref:`node` based on the `Simple PCIe FMC Carrier (SPEC)
<https://www.ohwr.org/project/spec/wikis/home>`_ and the `FMC ADC 100M 14b 4cha (FMC-ADC)
<https://www.ohwr.org/project/fmc-adc-100m14b4cha/wikis/home>`_.
.. important:: This :ref:`node` does not use the standard SPEC, because the FPGA (XC6SLX45T) is not
large enough for the complete design. Instead it uses the pin-compatible XC6SLX150T
FPGA (the rest of the board is exactly the same, only the FPGA chip is
different). This special version is available from the manufacturers of the SPEC
board upon request.
This :ref:`node` provides the possibility to generate WRTD :ref:`Messages <message>` based on
trigger events of the FMC-ADC, as well as to trigger the FMC-ADC from incoming WRTD :ref:`Messages
<message>`.
.. figure:: graphics/wrtd_ref_design_spec_adc_simple.png
:name: fig-ref_spec_adc
:width: 400pt
:align: center
:alt: alternate text
:figclass: align-center
SPEC150T-based FMC-ADC reference WRTD Node
The architecture of the :ref:`node` can be seen in :numref:`fig-ref_spec_adc`. The user communicates
with the :ref:`node` using one of the methods mentioned in :numref:`usage`. At the same time, the
user accesses the FMC-ADC core to configure everything not related to WRTD (acquisition parameters,
trigger source selection, data retrieval, etc.) using the existing `ADC library
<https://www.ohwr.org/project/adc-lib/wikis/home>`_. Internally, the :ref:`node` is running one
:ref:`application`, responsible for configuring the WRTD-related aspects of the FMC-ADC.
The five :ref:`Local Input Channels <local_channel>` are mapped as follows:
+-------------+---------------------------------+
| **Channel** | **Function** |
+=============+=================================+
| ``LC-I1`` | ADC Channel #1 internal trigger |
+-------------+---------------------------------+
| ``LC-I2`` | ADC Channel #2 internal trigger |
+-------------+---------------------------------+
| ``LC-I3`` | ADC Channel #3 internal trigger |
+-------------+---------------------------------+
| ``LC-I4`` | ADC Channel #4 internal trigger |
+-------------+---------------------------------+
| ``LC-I5`` | External trigger input |
+-------------+---------------------------------+
.. note:: In order for any of the :ref:`Local Input Channels <local_channel>` to produce an
:ref:`event`, the user must also properly configure the trigger source of the FMC-ADC via
the ADC library. This falls outside the scope of WRTD library.
The single :ref:`Local Output Channel <local_channel>` (``LC-O1``) is mapped to the "WRTD" trigger
input of the FMC-ADC.
.. note:: In order for :ref:`Local Output Channel <local_channel>` to trigger the FMC-ADC, the user
must also properly configure the trigger source of the FMC-ADC via the ADC library, to
enable triggering from the "WRTD" trigger input. This falls outside the scope of WRTD
library.
.. hint:: The User Application and the WRTD Application access different and separate parts of the
FMC-ADC, so there is no danger of accessing the same resources simultaneously.
.. _svec_ref_tdc_fd:
SVEC-based TDC+FD
=================
+----------------------------------------+------------+------------+
| **Parameter** | **Value** |
+========================================+============+============+
| # of :ref:`Applications <application>` | 2 |
+----------------------------------------+------------+------------+
| | **App #1** | **App #2** |
+----------------------------------------+------------+------------+
| Name | wrtd-tdc | wrtd-fd |
+----------------------------------------+------------+------------+
| Local input Channels | 5 | 0 |
+----------------------------------------+------------+------------+
| Local output Channels | 0 | 4 |
+----------------------------------------+------------+------------+
| Maximum :ref:`Rules <rule>` | 16 | 16 |
+----------------------------------------+------------+------------+
| Maximum :ref:`Alarms <alarm>` | 0 | 1 |
+----------------------------------------+------------+------------+
| Average input to Message latency | 20μs (TBC) | N.A. |
+----------------------------------------+------------+------------+
| Average Message to output latency | N.A. | 40μs (TBC) |
+----------------------------------------+------------+------------+
| Can receive Messages over WR | NO | YES |
+----------------------------------------+------------+------------+
| Can send Messages over WR | YES | NO |
+----------------------------------------+------------+------------+
This is a WRTD :ref:`node` based on the `Simple VME FMC Carrier (SVEC)
<https://www.ohwr.org/project/svec/wikis/home>`_, the `FMC Time to Digital Converter (FMC-TDC)
<https://www.ohwr.org/project/fmc-tdc-1ns-5cha-hw/wikis/home>`_ and the `FMC Fine Delay generator
(FMC-FD) <https://www.ohwr.org/project/fmc-delay-1ns-8cha/wikis/home>`_.
.. important:: The FMC-TDC should always be attached to "FMC Slot 1" of the SVEC, and the FMC-FD
should always be attached to "FMC Slot 2". It is not necessary though to have both
the FMCs attached, the :ref:`Node` will work if only one of the two (TDC or FD) is
present, as long as it is connected to the correct FMC slot.
The basic principle of this :ref:`node` is simple: it takes in external pulses on its FMC-TDC
inputs, timestamps them using WR time and converts them to WRTD :ref:`Messages <message>`, to be
sent over the WR network. Conversely, the :ref:`node` also receives WRTD :ref:`Messages <message>`
which are then used to generate pulses at a predefined moment on one of the FMC-FD outputs. As such,
it can be seen as a "pulse-to-message" and "message-to-pulse" converter with apllications in the
fields of pulse distribution, trigger synchronisation, etc.
.. figure:: graphics/wrtd_ref_design_svec_list_simple.png
:name: fig-ref_svec_list
:width: 400pt
:align: center
:alt: alternate text
:figclass: align-center
SVEC-based TDC+FD reference WRTD Node
The architecture of the :ref:`node` can be seen in :numref:`fig-ref_svec_list`. The user
communicates with the :ref:`node` using one of the methods mentioned in :numref:`usage`. Internally,
the :ref:`node` is running two :ref:`Applications <application>`, each on a dedicated CPU. One is
responsible for the FMC-TDC peripheral, while the other handles the FMC-FD.
The five :ref:`Local Input Channels <local_channel>` are mapped to the five inputs of the
FMC-TDC. Thus, :ref:`event_id` ``LC-I1`` corresponds to the first FMC-TDC channel, ``LC-I2`` to the
second one, and so on, up to ``LC-I5``.
The four :ref:`Local Output Channels <local_channel>` are mapped to the four outputs of the
FMC-FD. :ref:`event_id` ``LC-O1`` corresponds to the first FMC-FD output, and so on, up to
``LC-O4``.
.. hint:: It is possible for the User Application in :numref:`fig-ref_svec_list` to access directly
the FMC-TDC and FMC-FD cores by means of their respective libraries (not shown in
:numref:`fig-ref_svec_list`), in order to fine-tune them and/or change their default
behaviour. However this should be done with extreme care, as it could lead to a race
condition between the User Application and the WRTD Applications running inside the FPGA.
......@@ -15,7 +15,6 @@ The following specifications are relevant to and used by WRTD:
* `LXI Core Specification`_
* `LXI Event Messaging Extended Function`_
The remainder of this section presents the provided API, split in
.. _api_error:
Error Handling API
......@@ -168,11 +167,13 @@ parameter should be set to :c:macro:`WRTD_GLOBAL_REP_CAP_ID`.
int main(void) {
wrtd_dev *wrtd;
wrtd_status status;
bool log_empty;
status = wrtd_init("MT01", false, NULL, &wrtd);
status = wrtd_get_attr_bool(wrtd, WRTD_GLOBAL_REP_CAP_ID,
WRTD_ATTR_EVENT_LOG_EMPTY);
WRTD_ATTR_EVENT_LOG_EMPTY,
&log_empty);
wrtd_close(wrtd);
}
......@@ -351,12 +352,12 @@ Configuration of an Alarm happens by setting the relevant :ref:`Attributes <attr
status = wrtd_remove_all_alarms(wrtd);
/* Add three alarms */
status = wrtd_add_alarm("alarm1");
status = wrtd_add_alarm("alarm2");
status = wrtd_add_alarm("alarm3");
status = wrtd_add_alarm(wrtd, "alarm1");
status = wrtd_add_alarm(wrtd, "alarm2");
status = wrtd_add_alarm(wrtd, "alarm3");
/* Remove the 2nd alarm */
status = wrtd_remove_alarm("alarm2");
status = wrtd_remove_alarm(wrtd, "alarm2");
/* Get number of defined alarms */
status = wrtd_get_attr_int32(wrtd, WRTD_GLOBAL_REP_CAP_ID,
......@@ -410,12 +411,12 @@ Configuration of a Rule happens by setting the relevant :ref:`Attributes <attrib
status = wrtd_remove_all_rules(wrtd);
/* Add three rules */
status = wrtd_add_rule("rule1");
status = wrtd_add_rule("rule2");
status = wrtd_add_rule("rule3");
status = wrtd_add_rule(wrtd, "rule1");
status = wrtd_add_rule(wrtd, "rule2");
status = wrtd_add_rule(wrtd, "rule3");
/* Remove the 2nd rule */
status = wrtd_remove_rule("rule2");
status = wrtd_remove_rule(wrtd, "rule2");
/* Get number of defined rules */
status = wrtd_get_attr_int32(wrtd, WRTD_GLOBAL_REP_CAP_ID,
......@@ -447,7 +448,7 @@ Configuration of a Rule happens by setting the relevant :ref:`Attributes <attrib
status = wrtd_init("MT01", false, NULL, &wrtd);
/* Add a rule */
status = wrtd_add_rule("rule1");
status = wrtd_add_rule(wrtd, "rule1");
/* Set rule to listen for events coming on local channel
input 1 and generate a message on the network with
......
......@@ -180,7 +180,7 @@ Alarms API
>>> wrtd.set_attr_bool('alarm1', PyWrtd.WRTD_ATTR_ALARM_ENABLED, True)
>>> wrtd.get_attr_bool('alarm1', PyWrtd.WRTD_ATTR_ALARM_ENABLED)
True
>>> wrtd.disable_all_rules()
>>> wrtd.disable_all_alarms()
>>> wrtd.get_attr_bool('alarm1', PyWrtd.WRTD_ATTR_ALARM_ENABLED)
False
......@@ -207,7 +207,7 @@ Alarms API
.. automethod:: PyWrtd.get_alarm_name
.. code-block:: python
>>> wrtd.add_rule('alarm1')
>>> wrtd.add_alarm('alarm1')
>>> count = wrtd.get_attr_int32(PyWrtd.WRTD_GLOBAL_REP_CAP_ID, PyWrtd.WRTD_ATTR_ALARM_COUNT)
>>> print(count)
1
......
......@@ -36,14 +36,78 @@
/* By default use lxi-evntsvc. */
#define WRTD_UDP_PORT 5044
/* Functions defined by the user. */
/* The following functions are application-specific and need to be defined by the user. */
/**
* Check whether the WR link is up or not.
*
* If the application does not need this, write a function that returns always ``1``.
*
* @return ``1`` if true, ``0`` otherwise.
*/
static int wr_link_up(void);
/**
* Check whether the application is locked to the WR clock or not.
*
* If the application does not need this, write a function that returns always ``1``.
*
* @return ``1`` if true, ``0`` otherwise.
*/
static int wr_time_locked(void);
/**
* Check whether the WR time is valid.
*
* If the application does not need this, write a function that returns always ``1``.
*
* @return ``1`` if true, ``0`` otherwise.
*/
static int wr_time_ready(void);
/**
* Enable/disable locking of the application to the WR clock.
*
* If the application does not need this, write a function that does nothing.
*
* @param[in] enable set to ``1`` to enable, set to ``0`` to disable.
*/
static void wr_enable_lock(int enable);
/**
* Generate an output Event on a Local Channel.
*
* If the application does not need this, write a function that returns always ``0``.
*
* @param[in] ev pointer to a struct wrtd_event, representing the Event to send.
* @param[in] ch Local Channel number to use.
* @return ``0`` on success, or error code otherwise.
*/
static int wrtd_local_output(struct wrtd_event *ev, unsigned ch);
/**
* Return the delay in seconds that the application should wait before
* considering the WR link synced.
*
* If the application does not need this, write a function that returns always ``0``.
*
* @return Integer number of seconds to wait.
*/
static int wr_sync_timeout(void);
/**
* Function to perform any apllication-specific initialisation (runs once after reset).
*
* If the application does not need this, write a function that returns always ``0``.
*
* @return ``0`` on success, or error code otherwise.
*/
static int wrtd_user_init(void);
/**
* Function to perform the main tasks of the application. This will run in a loop.
*
* Typically the application will check here for incoming Events and pass them to
* WRTD via the wrtd_route_in() function. It might also want to check if output
* Events previously scheduled via wrtd_local_output() have been executed or not.
*
* If the application does not need this, write a function that returns always ``0``.
*
* @return ``0`` on success, or error code otherwise.
*/
static void wrtd_io(void);
/* Forward function declarations. */
......@@ -504,8 +568,12 @@ static void wrtd_route(struct wrtd_rule *rule, const struct wrtd_event *ev)
while (0);
}
/**
* Route an event coming from a Local Input, Network, or Alarm.
*
* @param[in] ev pointer to a struct wrtd_event, representing the received Event.
*/
#if WRTD_LOCAL_RX > 0 || WRTD_NET_RX > 0 || NBR_ALARMS > 0
/* Route an event coming from a local input, network, or alarm. */
static void wrtd_route_in(struct wrtd_event *ev)
{
struct wrtd_rule *rule;
......
......@@ -28,12 +28,15 @@ typedef struct wrtd_tstamp {
/** TAI seconds since 1/Jan/1970 (Unix Epoch Time).
This will overflow in 7/Feb/2106... */
uint32_t seconds;
/** Number of nanoseconds. Wraps at 10e9. */
/** Number of nanoseconds. Wraps at 1e9. */
uint32_t ns;
/** Number of fractional nanoseconds. Unit is 2e-32 ns. */
uint32_t frac;
} wrtd_tstamp;
/**
* WRTD Event
*/
struct wrtd_event {
/** Time of the event. */
struct wrtd_tstamp ts;
......
......@@ -953,7 +953,7 @@ wrtd_status wrtd_get_attr_tstamp(wrtd_dev *wrtd,
* - `log tstamp` is the timestamp of when the event was logged.
* - `event tstamp` is the timestamp of when the event happened.
* - `log type` is the type of the event.
* - `log tstamp` is the specific reason for this type of event.
* - `log reason` is the specific reason for this type of event.
*
* All event log entries have a fixed length of #WRTD_LOG_ENTRY_SIZE.
*
......@@ -973,7 +973,7 @@ wrtd_status wrtd_get_attr_tstamp(wrtd_dev *wrtd,
* finished executing. The exact meaning of this log type is application-specific.
* - `DISCARDED|NO SYNC` : An Event was discarded because the device was not syncrhonized
to White Rabbit. See also #WRTD_ATTR_STAT_RULE_MISSED_NOSYNC.
* - `DISCARDED|HOLD OFF`: An Event was discarded because violated the programmed hold-off
* - `DISCARDED|HOLD OFF`: An Event was discarded because it violated the programmed hold-off
* value. See also #WRTD_ATTR_STAT_RULE_MISSED_HOLDOFF.
* - `DISCARDED|TIME OUT`: An Event was discarded because it arrived too late. See also
* #WRTD_ATTR_STAT_RULE_MISSED_LATE.
......
......@@ -98,7 +98,7 @@ typedef enum wrtd_attr {
/** `RO` `bool` `global` True if the Event Log is empty. */
WRTD_ATTR_EVENT_LOG_EMPTY = __WRTD_ATTR_BASE + 0x00,
/** `RW` `bool` `global` Enable/dsiable the Event Log. */
/** `RW` `bool` `global` Enable/disable the Event Log. */
WRTD_ATTR_EVENT_LOG_ENABLED = __WRTD_ATTR_BASE + 0x01,
/** `RO` `bool` `global` True if the device is synchronized to White Rabbit time. */
WRTD_ATTR_IS_TIME_SYNCHRONIZED = __WRTD_ATTR_BASE + 0x02,
......@@ -128,16 +128,16 @@ typedef enum wrtd_attr {
/** `RW` `bool` `rule` Enable/disable a Rule. */
WRTD_ATTR_RULE_ENABLED = __WRTD_ATTR_BASE + 0x21,
/** `RW` `int32` `rule` Specifies the number of times a Rule will fire before becoming
automatically disabled. 0 means infinite. 1 means that the alarm will fire only once.
automatically disabled. 0 means infinite. 1 means that the Rule will fire only once.
When read, it returns the remaining repetitions. */
WRTD_ATTR_RULE_REPEAT_COUNT = __WRTD_ATTR_BASE + 0x22,
/** `RW` `string` `rule` Get/set Rule source. Rule sources can be:
- Local source Event IDs (in the form of **LCI-x**)
- Local source Event IDs (in the form of **LC-I<x>**)
- Alarm IDs (any ID with an **alarm** prefix)
- Any other string which will be interpreted as a network message Event ID. */
WRTD_ATTR_RULE_SOURCE = __WRTD_ATTR_BASE + 0x23,
/** `RW` `string` `rule` Get/set Rule destinations. Rule destinations can be:
- Local destination Event IDs (in the form of **LCO-x**)
- Local destination Event IDs (in the form of **LC-O<x>**)
- Any other string which will be interpreted as a network message Event ID. */
WRTD_ATTR_RULE_DESTINATION = __WRTD_ATTR_BASE + 0x24,
/** `RW` `bool` `rule` If true, events that arrive late (with a timestamp in
......
......@@ -34,18 +34,16 @@ class wrtd_tstamp(Structure):
yield 'frac' , self.frac
@decorator.decorator
def encode_arguments(func):
def encode_arguments(func, *args, **kwargs):
"""Used to convert arguments from strings to bytes"""
def wrapper(self, *args, **kwargs):
encoded = []
for arg in args:
if(type(arg) == str):
encoded.append(arg.encode('utf-8'))
else:
encoded.append(arg)
args = tuple(encoded)
return func(self, *args, **kwargs)
return wrapper
encoded = []
for arg in args:
if(type(arg) == str):
encoded.append(arg.encode('utf-8'))
else:
encoded.append(arg)
args = tuple(encoded)
return func(*args, **kwargs)
class PyWrtd():
"""Top-level Python wrapper class for WRTD library.
......@@ -426,7 +424,7 @@ class PyWrtd():
"""
Corresponds to C library :cpp:func:`wrtd_clear_event_log_entries`.
"""
self.wrtd_lib.clear_event_log_entries(self.wrtd_p)
self.wrtd_lib.wrtd_clear_event_log_entries(self.wrtd_p)
def get_next_event_log_entry(self):
"""
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment