Commit 4ec717f7 authored by Federico Vaga's avatar Federico Vaga

Add documentation

Mainly software
Signed-off-by: Federico Vaga's avatarFederico Vaga <federico.vaga@cern.ch>
parent 6c5030b2
_build
_static
doxygen-lib-output
*.htm
\ No newline at end of file
# SPDX-FileCopyrightText: 2020 CERN (home.cern)
#
# SPDX-License-Identifier: CC0-1.0
# Minimal makefile for Sphinx documentation
#
# You can set these variables from the command line, and also
# from the environment for the first two.
SPHINXOPTS = -Drelease=$(shell git describe) -Dversion=$(shell git describe | cut -d "-" -f 1 | tr -d "v")
SPHINXBUILD ?= sphinx-build
SOURCEDIR = .
BUILDDIR = _build
# Put it first so that "make" without argument is like "make help".
help:
@$(SPHINXBUILD) -M help "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O)
.PHONY: help Makefile doxygen
# Catch-all target: route all unknown targets to Sphinx using the new
# "make mode" option. $(O) is meant as a shortcut for $(SPHINXOPTS).
%: Makefile
$(MAKE) doxygen TARGET=$@
$(MAKE) -C img all
$(MAKE) -C gateware/regs all
@$(SPHINXBUILD) -M $@ "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O)
clean:
$(MAKE) -C img clean
$(MAKE) -C gateware/regs clean
@$(SPHINXBUILD) -M $@ "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O)
GIT_VERSION = $(shell cd $(src); git describe --dirty --long --tags)
doxygen:
ifeq ($(TARGET),clean)
@echo "Remove Doxygen files"
@rm -rf doxygen-lib-output
else
GIT_VERSION=$(GIT_VERSION) doxygen ./doxygen-fmctdc-config
endif
# SPDX-FileCopyrightText: 2022 CERN (home.cern)
#
# SPDX-License-Identifier: CC0-1.0
# Configuration file for the Sphinx documentation builder.
#
# This file only contains a selection of the most common options. For a full
# list see the documentation:
# https://www.sphinx-doc.org/en/master/usage/configuration.html
# -- Path setup --------------------------------------------------------------
# If extensions (or modules to document with autodoc) are in another directory,
# add these directories to sys.path here. If the directory is relative to the
# documentation root, use os.path.abspath to make it absolute, like shown here.
import os
import sys
sys.path.append(os.path.abspath('../lib/PyFmcTdc'))
sys.path.append(os.path.abspath('../lib'))
# -- Project information -----------------------------------------------------
project = 'FMC-TDC 1ns 5cha'
copyright = u'2022, CERN, documentation released under CC-BY-SA-4.0'
author = 'Federico Vaga <federico.vaga@cern.ch>'
# The suffix(es) of source filenames.
# You can specify multiple suffix as a list of string:
#
# source_suffix = ['.rst', '.md']
source_suffix = '.rst'
# The master toctree document.
master_doc = 'index'
# -- General configuration ---------------------------------------------------
# Add any Sphinx extension module names here, as strings. They can be
# extensions coming with Sphinx (named 'sphinx.ext.*') or your custom
# ones.
extensions = ['sphinx.ext.autodoc',
'sphinx.ext.todo',
'sphinx.ext.coverage',
'sphinx.ext.graphviz',
'breathe'
]
# Add any paths that contain templates here, relative to this directory.
templates_path = ['_templates']
# List of patterns, relative to source directory, that match files and
# directories to ignore when looking for source files.
# This pattern also affects html_static_path and html_extra_path.
exclude_patterns = ['build_env', '_build', 'Thumbs.db', '.DS_Store']
# -- Options for HTML output -------------------------------------------------
# The theme to use for HTML and HTML Help pages. See the documentation for
# a list of builtin themes.
#
html_theme = 'sphinx_rtd_theme'
# If true, links to the reST sources are added to the pages.
#
html_show_sourcelink = False
# If true, "Created using Sphinx" is shown in the HTML footer. Default is True.
#
html_show_sphinx = False
# Add any paths that contain custom static files (such as style sheets) here,
# relative to this directory. They are copied after the builtin static files,
# so a file named "default.css" will overwrite the builtin "default.css".
html_static_path = ['_static']
# -- Options for LaTeX output ---------------------------------------------
# Grouping the document tree into LaTeX files. List of tuples
# (source start file, target name, title,
# author, documentclass [howto, manual, or own class]).
latex_documents = [
(master_doc,
'FMCTDC1ns5cha.tex',
'FMC TDC 1ns 5 Channel Documentation',
'Federico Vaga \\textless{}federico.vaga@cern.ch\\textgreater{}',
'manual'),
]
breathe_projects = {
"fmctdc-lib":"doxygen-lib-output/xml/",
}
breathe_projects_source = {
"fmctdc-lib" : ( "../software/lib/", ["fmctdc-lib.h",
"fmctdc-lib.c",
"fmctdc-lib-math.c"
])
}
breathe_default_project = "fmctdc-lib"
PROJECT_NAME = "FMC TDC - Software"
# Copyright (c) 2022 CERN (home.cern)
# SPDX-License-Identifier: CC0-1.0
PROJECT_NAME = "FMC TDC - Library"
PROJECT_NUMBER = $(GIT_VERSION)
PROJECT_BRIEF = $(BRIEF)
PROJECT_LOGO =
OUTPUT_DIRECTORY = $(OUTPUT)
OUTPUT_DIRECTORY = doxygen-lib-output
CREATE_SUBDIRS = YES
TAB_SIZE = 8
OPTIMIZE_OUTPUT_FOR_C = YES
EXTRACT_STATIC = NO
EXTRACT_STATIC = YES
CASE_SENSE_NAMES = YES
WARN_NO_PARAMDOC = YES
INPUT = ../lib readme.md
INPUT = ../software/lib
RECURSIVE = YES
EXCLUDE = $(EXCLUDE_FILES)
EXCLUDE = ../software/lib/PyFmcTdc
GENERATE_HTML = YES
GENERATE_LATEX = YES
GENERATE_XML = YES
..
SPDX-License-Identifier: CC-BY-SA-4.0
SPDX-FileCopyrightText: 2022 CERN
============
The Gateware
============
About Source Code
=================
Build from Sources
------------------
The fmc-tdc hdl design make use of the ``hdlmake`` tool. It
automatically fetches the required hdl cores and libraries. It also
generates Makefiles for synthesis/par and simulation.
Here is the procedure to build the FPGA binary image from the hdl
source.::
# Install ``hdlmake`` (version 3.4).
# Get fmc-adc hdl sources.
git clone git://ohwr.org/project/fmc-adc-100m14b4cha.git <src_dir>
# Goto the synthesis directory.
cd <src_dir>/hdl/<carrier>/syn/
# Fetch the dependencies and generate a synthesis Makefile.
hdlmake
# Perform synthesis, place, route and generate FPGA bitstream.
make
Source Code Organisation
------------------------
hdl/rtl/
ADC specific hdl sources.
hdl/cheby/
ADC specific ``cheby`` sources, html documentation and C header
file.
hdl/ip_cores/
Location of fetched hdl cores and libraries.
hdl/platform/<platform>
Platform related hdl sources.
hdl/top/<design>
Top-level hdl module for selected design.
hdl/syn/<design>
Synthesis directory for selected design. This is where the
synthesis top manifest, the design constraints and the ISE project
are stored. For each release, the synthesis, place&route and timing
reports are also saved here.
hdl/testbench/
Simulation files and testbenches.
Dependencies
------------
The fmc-adc gateware depends on the following hdl cores and libraries:
`General Cores`_, `DDR3 SP6 core`_, `GN4124 core`_ (SPEC only),
`SPEC`_ (SPEC only) `VME64x Slave`_ (SVEC only), `SVEC`_ (SVEC only),
`WR Cores`_.
These dependencies are managed with GIT submodules. Whenever you checkout
a different branch remember to update the submodules as well.::
git submodule sync
git submodule update
.. _`General Cores`: http://www.ohwr.org/projects/general-cores
.. _`DDR3 SP6 core`: http://www.ohwr.org/hdl-core-lib/ddr3-sp6-core
.. _`GN4124 core`: http://www.ohwr.org/hdl-core-lib/gn4124-core
.. _`VME64x Slave`: http://www.ohwr.org/hdl-core-lib/vme64x-core
.. _`SPEC`: https://ohwr.org/project/spec
.. _`SVEC`: https://ohwr.org/project/svec
.. _`Wr cores`: https://ohwr.org/project/wr-cores
..
SPDX-License-Identifier: CC-BY-SA-4.0
SPDX-FileCopyrightText: 2022 CERN
==============
The Memory Map
==============
Following the memory map for the part of the ADC design that drives
the FMC-TDC-1NS-5CH modules.
.. only:: latex
.. warning::
Unfortunatelly we are not able to include the memory map in PDF format.
Please for the memory map refer to the online documentation,
.. raw:: html
:file: regs/fmc_tdc_mezzanine_mmap.htm
Supported Designs
=================
Here you can find the complete memory MAP for the supported
designs. This will include the TDC register as well as the carrier
registers and any other component used in an FMC-TDC-1NS-5CH design.
.. toctree::
:maxdepth: 1
:caption: Table of Contents
spec_ref_fmc_tdc
svec_ref_fmc_tdc
# SPDX-FileCopyrightText: 2020 CERN (home.cern)
#
# SPDX-License-Identifier: CC0-1.0
TOP_DIR = ../../..
HTML := spec_base_regs.htm
HTML += svec_base_regs.htm
HTML += svec_ref_fmc_tdc_mmap.htm
HTML += spec_ref_fmc_tdc_mmap.htm
HTML += fmc_tdc_mezzanine_mmap.htm
all: $(HTML)
.PHONY: clean
CHEBY_BUILD=(cd $(dir $<); cheby -i $(notdir $<) --gen-doc --doc html) > $@
fmc_tdc_mezzanine_mmap.htm: $(TOP_DIR)/hdl/cheby/fmc_tdc_mezzanine_mmap.cheby
$(CHEBY_BUILD)
spec_ref_fmc_tdc_mmap.htm: $(TOP_DIR)/hdl/cheby/spec_ref_fmc_tdc_mmap.cheby
$(CHEBY_BUILD)
svec_ref_fmc_tdc_mmap.htm: $(TOP_DIR)/hdl/cheby/svec_ref_fmc_tdc_mmap.cheby
$(CHEBY_BUILD)
svec_base_regs.htm: $(TOP_DIR)/hdl/ip_cores/svec/hdl/rtl/svec_base_regs.cheby
$(CHEBY_BUILD)
spec_base_regs.htm: $(TOP_DIR)/hdl/ip_cores/spec/hdl/rtl/spec_base_regs.cheby
$(CHEBY_BUILD)
clean:
@rm -f *.md *.rst *.htm
..
SPDX-License-Identifier: CC-BY-SA-4.0
SPDX-FileCopyrightText: 2022 CERN
=====================
SPEC FMC-TDC-1NS-5CHA
=====================
The memory map is divided in two parts: the `Carrier`_ part common to
all SPEC designs, and the `FMC-TDC-1NS-5CHA`_ part specific to the
FMC-TDC-1NS-5CHA mezzanine.
Carrier
=======
.. raw:: html
:file: regs/spec_base_regs.htm
FMC-TDC-1NS-5CHA
================
.. raw:: html
:file: regs/spec_ref_fmc_tdc_mmap.htm
..
SPDX-License-Identifier: CC-BY-SA-4.0
SPDX-FileCopyrightText: 2022 CERN
=================
SVEC FMC ADC 100M
=================
The memory map is divided in two parts: the `Carrier`_ part common to
all SPEC designs, and the `FMC-TDC-1NS-5CHA`_ part specific to the
FMC-TDC-1NS-5CHA mezzanine.
Carrier
=======
.. raw:: html
:file: regs/svec_base_regs.htm
FMC-TDC-1NS-5CHA
================
.. raw:: html
:file: regs/svec_ref_fmc_tdc_mmap.htm
# SPDX-FileCopyrightText: 2022 CERN (home.cern)
#
# SPDX-License-Identifier: CC0-1.0
SVG=$(wildcard *.svg)
PDF=$(SVG:.svg=.pdf)
.PHONY: all
all: $(PDF)
%.pdf : %.svg
inkscape $< -o $@ || inkscape --without-gui $< -A $@
clean:
rm -f $(PDF)
show:
$(info all svg: $(SVG))
$(info all pdf: $(PDF))
.. Copyright (c) 2022 CERN (home.cern)
SPDX-License-Identifier: CC-BY-SA-4.0
.. FMC-TDC-1NS-5CH documentation master file, created by
sphinx-quickstart on Thu Aug 6 14:57:13 2020.
You can adapt this file completely to your liking, but it should at least
contain the root `toctree` directive.
FMC-TDC 1ns 5 Channel Documentation
===================================
.. toctree::
:maxdepth: 2
:caption: Table of Contents
introduction
gateware/index
software/index
gateware/memory-map
.. Copyright (c) 2022 CERN (home.cern)
SPDX-License-Identifier: CC-BY-SA-4.0
.. _introduction:
------------
Introduction
------------
This document describes the gateware developed to support the
FmcTDC 1n 5channel (later refered to as fmc-tdc) mezzanine card on the
`SPEC`_ and `SVEC`_ carrier cards. The gateware is the HDL code used
to generate the bitstream that configures the FPGA on the carrier
(sometimes also called firmware). The gateware architecture is
described in detail. The configuration and operation of the fmc-tdc
is also explained. The Linux driver and basic tools are explained as
well. On the other hand, this manual is not intended to provide
information about the hardware design.
Repositories and Releases
=========================
The `FMC TDC 1ns 5 Channels`_ is hosted on
the `Open HardWare Repository`_. The main development happens
here. You can clone the GIT project with the following command::
git clone https://ohwr.org/project/fmc-tdc.git
Within the GIT respository, releases are marked with a TAG named
using the `Semantic Versioning`_. For example the latest release is
``v8.0.0``. You can also find older releases with a different versioning
mechanism.
For each release we will publish the FPGA bitstream for all supported
carrier cards (`FPGA Bitstream Page`_). For the Linux driver we can't
release the binary because it depends on the Linux version on which it
will run. For details about how to build the Linux driver for your
kernel please have a look at :ref:`Compile And Install
<drv_build_install>` section in :doc:`Driver's Documentation
<software/driver>`.
Documentation License
=====================
This work is licensed under the Creative Commons
Attribution-ShareAlike 4.0 International License. To view a copy of
this license, visit http://creativecommons.org/licenses/by-sa/4.0/.
.. _SPEC: http://www.ohwr.org/projects/spec
.. _SVEC: http://www.ohwr.org/projects/svec
.. _`FMC TDC 1ns 5 Channels`: https://ohwr.org/project/fmc-tdc
.. _`Open HardWare Repository`: https://ohwr.org/
.. _`Semantic Versioning`: https://semver.org/
.. _`FPGA Bitstream Page`: https://ohwr.org/project/fmc-tdc/wikis/Documents/Bitstreams
alabaster==0.7.12
appdirs==1.4.3
Babel==2.8.0
CacheControl==0.12.6
certifi==2019.11.28
chardet==3.0.4
colorama==0.4.3
contextlib2==0.6.0
distlib==0.3.0
distro==1.4.0
docutils==0.16
html5lib==1.0.1
idna==2.8
imagesize==1.2.0
Jinja2==2.11.2
lockfile==0.12.2
MarkupSafe==1.1.1
msgpack==0.6.2
packaging==20.3
pep517==0.8.2
progress==1.5
Pygments==2.6.1
pyparsing==2.4.6
pytoml==0.1.21
pytz==2020.1
requests==2.23.0
retrying==1.3.3
six==1.14.0
snowballstemmer==2.0.0
Sphinx==3.1.2
sphinx-rtd-theme==0.5.0
sphinxcontrib-applehelp==1.0.2
sphinxcontrib-devhelp==1.0.2
sphinxcontrib-htmlhelp==1.0.3
sphinxcontrib-jsmath==1.0.1
sphinxcontrib-qthelp==1.0.3
sphinxcontrib-serializinghtml==1.1.4
urllib3==1.25.8
webencodings==0.5.1
This diff is collapsed.
..
SPDX-License-Identifier: CC-BY-SA-4.0
SPDX-FileCopyrightText: 2022 CERN
============
The Software
============
.. toctree::
:maxdepth: 1
:caption: Contents
driver
tools
library
library-api
.. Copyright (c) 2022 CERN (home.cern)
SPDX-License-Identifier: CC-BY-SA-4.0
The Library API
================
.. autodoxygenfile:: fmctdc-lib.h
..
SPDX-License-Identifier: CC-BY-SA-4.0
SPDX-FileCopyrightText: 2022 CERN
The Library
===========
Here you can find all the information about the *fmc-tdc* API and the
main library behaviour that you need to be aware of to write
applications.
This document introduces the developers to the development with the ADC library.
Here you can find an overview about the API, the rational behind it and
examples of its usage. It is not the purpose of the document to describe
the API details. The complete API is available in the Library API document.
.. note::
The TDC hardware design diverged into different buffering
structures. One based on FIFOs for `SVEC`_, and one based on
double-buffering in DDR for `SPEC`_. The API tries to provide the same
user-experience, however this is not always possible. Functions having
different behaviour are properly declaring it in their documentation.
.. note::
This document provides also snippet of code from `example.c`. This
is only to show you an example, please avoid to blindly copy and
paste.
Initialization and Cleanup
--------------------------
The library may keep internal information, so the application should
call its initialization function :cpp:func:`fmctdc_init()`. After use,
it should call the exit function :cpp:func:`fmctdc_exit()` to release
any internal data.
.. note::
:cpp:func:`fmctdc_exit()` is not mandatory, the operating system
releases anything in any case -- the library doesn't leave unexpected
files in persistent storage.
These functions don't do anything at this point, but they may be
implemented in later releases. For example, the library may scan the
system and cache the list of peripheral cards found, to make
later *open* calls faster. For this reason it is **recommended**
to, at least, initialize and release the library before starting.
Following an example from the ``example.c`` code available under ``tools``
.. literalinclude:: ../../software/tools/example.c
:language: c
:lines: 54-62
Error Reporting
----------------
Each library function returns values according to standard *libc*
conventions: -1 or NULL (for functions returning ``int`` or pointers,
resp.) is an error indication. When error happens, the :manpage:`errno`
variable is set appropriately.
The :manpage:`errno` values can be standard Posix items like
``EINVAL``, or library-specific values, for example
``ADC_ERR_VMALLOC`` (*driver vmalloc allocator not available*). All
library-specific error values have a value greater than 4096, to
prevent collision with standard values. To convert such values to a
string please use :cpp:func:`fmctdc_strerror()`
Following an example from the ``example.c`` code available under ``tools``
.. literalinclude:: ../../software/tools/example.c
:language: c
:lines: 74-75
Opening and closing
--------------------
Each device must be opened before use by calling :cpp:func:`fmctdc_open()`,
and it should be closed after use by calling :cpp:func:`fmctdc_close()`.
.. note ::
:cpp:func:`fmctdc_close()` is not mandatory, but it is recommended, to
close if the process is going to terminate, as the library has no
persistent storage to clean up -- but there may be persistent buffer
storage allocated, and :cpp:func:`fmctdc_close()` may release it in
future versions.
The data structure returned by :cpp:func:`fmctdc_open()` is an opaque pointer
used as token to access the API functions. The user is not supposed to use
or modify this pointer.
Another kind of open function has been provided to satisfy CERN's developers
needs. Function :cpp:func:`fmctdc_open_by_lun()` is the open by LUN
(*Logic Unit Number*); here the LUN concept reflects the *CERN* one.
The usage is exactly the same as :cpp:func:`fmctdc_open()` only that it uses
the LUN instead of the device ID.
No automatic action is take by :cpp:func:`fmctdc_open()`. Hence, you
may want to flush the buffers before starting a new acquisition
session. You can do this with :cpp:func:`fmctdc_flush()`
.. literalinclude:: ../../software/tools/example.c
:language: c
:lines: 72-90
Configuration And Status
------------------------
The TDC configuration API is based on a number of getter and setter
function for each option. These include: *termination*, *IRQ
coalescing timeout*, *board time*, *white-rabbit*, *timestamp mode*.
The *termination* options allows you to set the 50 Ohm channel
termination. You can use the following getter and setter:
:cpp:func:`fmctdc_get_termination()`,
:cpp:func:`fmctdc_set_termination()`.
.. literalinclude:: ../../software/tools/example.c
:language: c
:lines: 123-128
The *IRQ coalescing timeout* option allows to force an IRQ when the
timeout expire to inform the driver that there is at least one pending
timestamp to be transfered. You can use the following getter and setter:
:cpp:func:`fmctdc_coalescing_timeout_get()`,
:cpp:func:`fmctdc_coalescing_timeout_set()`.
.. literalinclude:: ../../software/tools/example.c
:language: c
:lines: 131-136
The TDC main functionality is to timestap incoming pulses. To assign a
timestamp the board needs a time reference. This can be provided by
the on-board clock, or by the more accurate white-rabbit network. You
can enable or disable white-rabbit using
:cpp:func:`fmctdc_wr_mode()`. You can check the white-rabbit status
with :cpp:func:`fmctdc_check_wr_mode()`. When working with
white-rabbit the time reference is handled by the white-rabbit
network.
.. literalinclude:: ../../software/tools/example.c
:language: c
:lines: 139-144
If you do not have white-rabbit connected to the TDC, or simply this
is not what you want, then be sure to disable. When white-rabbit is
disabled the TDC will use the on-board clock to keep a time
reference. However, in this scenario the user is asked to set first
the time using :cpp:func:`fmctdc_set_time()` or
:cpp:func:`fmctdc_set_host_time()`.
.. literalinclude:: ../../software/tools/example.c
:language: c
:lines: 147-149
Whater you are using white-rabbit or not, you can get the current
board time with :cpp:func:`fmctdc_get_time()`.
.. literalinclude:: ../../software/tools/example.c
:language: c
:lines: 150-152
Still about time, the user can add it's own offset without changing
the timebase using :cpp:func:`fmctdc_get_offset_user()` and
:cpp:func:`fmctdc_set_offset_user()`.
.. literalinclude:: ../../software/tools/example.c
:language: c
:lines: 155-160
Finally, you can monitor the board temperature using
:cpp:func:`fmctdc_read_temperature()`, and pulse and timestamps
statistics with :cpp:func:`fmctdc_stats_recv_get()` and
:cpp:func:`fmctdc_stats_trans_get()`.
.. literalinclude:: ../../software/tools/example.c
:language: c
:lines: 226-231
.. note::
If it can be useful there is one last status function in the API
used to detect the transfer mode between the driver and the
board. This function is :cpp:func:`fmctdc_transfer_mode()`
Timestamp buffering has its own set of options. Buffering in hardware
is fixed, it can't be configured, so what we are going to describe
here is the Linux device driver buffering configuration. Because the
TDC driver is based on `ZIO`_, then you can choose the buffer
allocator type. You can handle this option with the pair:
:cpp:func:`fmctdc_get_buffer_type()` and
:cpp:func:`fmctdc_set_buffer_type()`.
.. literalinclude:: ../../software/tools/example.c
:language: c
:lines: 163-168
You can configure - and get - the buffer size (number of
timestamps) with: :cpp:func:`fmctdc_get_buffer_len()` and
:cpp:func:`fmctdc_set_buffer_len()`. Beware, that this function works
only when using :cpp:any:`FMCTDC_BUFFER_VMALLOC`.
.. literalinclude:: ../../software/tools/example.c
:language: c
:lines: 171-176
Finally, you can select between to modes to handle buffer's overflows:
:cpp:any:`FMCTDC_BUFFER_CIRC` and :cpp:any:`FMCTDC_BUFFER_FIFO`. The
first will discard old timestamps to make space for the new ones, the
latter will discard any new timestamp until the buffer get
consumed. To configure this option you can use:
:cpp:func:`fmctdc_get_buffer_mode()` and
:cpp:func:`fmctdc_set_buffer_mode()`.
.. literalinclude:: ../../software/tools/example.c
:language: c
:lines: 179-184
Acquisiton
----------
Before actually being able to get timestamps, the TDC acquisition must
be enabled. The acquisition can be *enabled* or *disabled* through its
gateware using, respectivily, :cpp:func:`fmctdc_channel_enable()` and
:cpp:func:`fmctdc_channel_disable()`.
.. literalinclude:: ../../software/tools/example.c
:language: c
:lines: 194-204
You have to may functions to read timestamp :cpp:func:`fmctdc_read()`
and :cpp:func:`fmctdc_fread()`. As the name may suggest, the first
behaves like :manpage:`read` and the second as :manpage:`fread`.
.. literalinclude:: ../../software/tools/example.c
:language: c
:lines: 218-222
If you need to flush the buffer, you can use :cpp:func:`fmctdc_flush()`.
.. literalinclude:: ../../software/tools/example.c
:language: c
:lines: 79-81
Timestamp Math
--------------
The TDC library API has functions to support timestamp math. They
allow you to *add*, *subtract*, *compare*, *normalize*, and
*approximate*. These functions are: :cpp:func:`fmctdc_ts_add()`,
:cpp:func:`fmctdc_ts_sub()`, :cpp:func:`_fmctdc_tscmp()`,
:cpp:func:`fmctdc_ts_norm()`, :cpp:func:`fmctdc_ts_ps()`,and
:cpp:func:`fmctdc_ts_approx_ns()`.
.. _`ZIO`: https://www.ohwr.org/project/zio
.. _`SVEC`: https://www.ohwr.org/projects/svec
.. _`SPEC`: https://www.ohwr.org/projects/spec
..
SPDX-License-Identifier: CC-BY-SA-4.0
SPDX-FileCopyrightText: 2022 CERN
Tools
=====
The driver is distributed with a few tools living in the ``tools/``
subdirectory and they do not use any dedicated library, instead
they do raw accesses to the driver. The programs are meant to provide
examples about the use of the driver and library interface
Termination Configuration
-------------------------
Reading Temperature
-------------------
Getting And Setting Board Time
------------------------------
Read Timestamps
---------------
User Offset Configuration
-------------------------
Calibration Data
----------------
......@@ -651,7 +651,9 @@ int fmctdc_get_buffer_len(struct fmctdc_board *userb, unsigned int channel)
* Internally, the buffer allocates memory in chunks of minimun 1KiB. This
* means, for example, that if you ask for 65 timestamp the buffer will
* allocate space for 128. This because 64 timestamps fit in 1KiB, to store
* 65 we need 2KiB (128 timestamps)
* 65 we need 2KiB (128 timestamps).
*
* NOTE: it works only with the VMALLOC allocator.
*/
int fmctdc_set_buffer_len(struct fmctdc_board *userb, unsigned int channel,
unsigned int length)
......
......@@ -130,25 +130,16 @@ struct fmctdc_time {
};
/**
* @file fmctdc-lib.c
*/
/**
* @defgroup libutil Utilities
/*
* Set of library utilities
* @{
*/
extern const char *fmctdc_strerror(int err);
extern int fmctdc_init(void);
extern void fmctdc_exit(void);
/**@}*/
/**
* @defgroup libboard Board Configuration
/*
* Set of function to configure TDC board and retrieve information
* about the current status
* @{
*/
extern int fmctdc_set_time(struct fmctdc_board *b, struct fmctdc_time *t);
extern int fmctdc_get_time(struct fmctdc_board *b, struct fmctdc_time *t);
......@@ -156,14 +147,11 @@ extern int fmctdc_set_host_time(struct fmctdc_board *b);
extern int fmctdc_wr_mode(struct fmctdc_board *b, int on);
extern int fmctdc_check_wr_mode(struct fmctdc_board *b);
extern float fmctdc_read_temperature(struct fmctdc_board *b);
/**@}*/
/**
* @defgroup libchan Channel Configuration
/*
* Set of function to configure TDC channels and retrieve information
* about the current status
* @{
*/
extern int fmctdc_channel_status_set(struct fmctdc_board *userb,
unsigned int channel,
......@@ -209,12 +197,8 @@ extern int fmctdc_ts_mode_get(struct fmctdc_board *userb,
unsigned int channel,
enum fmctdc_ts_mode *mode);
/**@}*/
/**
* @defgroup libacq Time-stamps Acquisition
/*
* Set of functions to read time-stamps from the board
* @{
*/
extern struct fmctdc_board *fmctdc_open(int dev_id);
extern struct fmctdc_board *fmctdc_open_by_lun(int lun);
......@@ -224,15 +208,10 @@ extern int fmctdc_fread(struct fmctdc_board *b, unsigned int channel,
extern int fmctdc_fileno_channel(struct fmctdc_board *b, unsigned int channel);
extern int fmctdc_read(struct fmctdc_board *b, unsigned int channel,
struct fmctdc_time *t, int n, int flags);
extern int fmctdc_readhw(struct fmctdc_board *b, unsigned int channel,
struct ft_hw_timestamp *t, int n, int flags);
extern int fmctdc_flush(struct fmctdc_board *userb, unsigned int channel);
/**@}*/
/**
* @defgroup libstats Statistics
/*
* Set of functions to get statistics
* @{
*/
extern int fmctdc_stats_recv_get(struct fmctdc_board *userb,
unsigned int channel,
......@@ -240,18 +219,10 @@ extern int fmctdc_stats_recv_get(struct fmctdc_board *userb,
extern int fmctdc_stats_trans_get(struct fmctdc_board *userb,
unsigned int channel,
uint32_t *val);
/**@}*/
/**
*@file fmctdc-lib-math.c
*/
/**
* @defgroup libmath Time-Stamp Math
* Set of mathematical functions on time-stamps
* @{
*/
extern uint64_t fmctdc_ts_approx_ns(struct fmctdc_time *a);
extern uint64_t fmctdc_ts_ps(struct fmctdc_time *a);
extern void fmctdc_ts_norm(struct fmctdc_time *a);
......@@ -262,7 +233,6 @@ extern void fmctdc_ts_add(struct fmctdc_time *r,
const struct fmctdc_time *a,
const struct fmctdc_time *b);
extern int _fmctdc_tscmp(struct fmctdc_time *a, struct fmctdc_time *b);
/**@}*/
/**
* libfmctdc version string
......
......@@ -8,4 +8,5 @@ fmc-tdc-tstamp
fmc-tdc-offset
fmc-tdc-perftest
fmc-tdc-calibration
example
Makefile.specific
......@@ -19,6 +19,8 @@ TESTS = fmc-tdc-term \
fmc-tdc-offset \
fmc-tdc-calibration
OTHERS = example
CFLAGS = -ggdb -I. -I$(LIBTDC) -I../kernel -Wall -Werror $(EXTRACFLAGS)
GIT_VERSION := $(shell git describe --dirty --long --tags)
CFLAGS += -DGIT_VERSION="\"$(GIT_VERSION)\""
......@@ -29,10 +31,12 @@ LDLIBS = -lfmctdc -lrt
CPPCHECK ?= cppcheck
all: $(TESTS)
all: $(TESTS) $(OTHERS)
$(TESTS): $(COMMON_SRCS:.c=.o) $(LIBTDC)/libfmctdc.a
$(OTHERS): $(LIBTDC)/libfmctdc.a
fmc-tdc-list:
clean:
......
// SPDX-License-Identifier: GPL-3.0-or-later
// SPDX-Copyright: 2022 CERN
/*
* Author: Federico Vaga <federico.vaga@cern.ch>
*
* This is an example program that shows the different part of the library
* in action.
*
*
* This is part of the documentation, so when you change it **REMEMBER** to
* update the references in documents in `doc/`.
*
* The reason to have the example here as a true program is that we can always
* compile it and run it, so that we can validate the example.
* This way, at least for this aspect, the documentation in always aligned.
*
* Do not try to optimize this code, the purpose is to show code, highlight
* snippet and being able to refer to it from the documentation
*/
#include <assert.h>
#include <errno.h>
#include <inttypes.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <fcntl.h>
#include <fmctdc-lib.h>
static const unsigned int channel = 0;
static const int termination = 0;
static const enum fmctdc_buffer_type buffer_type = FMCTDC_BUFFER_VMALLOC;
static const enum fmctdc_buffer_mode buffer_mode = FMCTDC_BUFFER_FIFO;
static const unsigned int buffer_len= 128;
static const int32_t offset_user = 0;
static const int wr_mode = 0;
static const struct fmctdc_time time = {0, 0, 0, 0, 0};
static char *prog_name;
static int fetch_and_process(struct fmctdc_board *tdc);
static int acquire(struct fmctdc_board *tdc);
static int config(struct fmctdc_board *tdc);
static int config_and_acquire(struct fmctdc_board *tdc);
static int use_fmctdc_library();
int main(int argc, char *argv[])
{
int err;
prog_name = argv[0];
err = fmctdc_init();
if (err)
exit(EXIT_FAILURE);
err = use_fmctdc_library();
if (err)
exit(EXIT_FAILURE);
fmctdc_exit(); /* optional, indeed in the error condition
we do not do it */
exit(EXIT_SUCCESS);
}
static int use_fmctdc_library()
{
struct fmctdc_board *tdc;
int err;
/* Open the TDC */
tdc = fmctdc_open(0x0000);
if (!tdc) {
fprintf(stderr, "%s: Cannot open device: %s\n",
prog_name, fmctdc_strerror(errno));
return -1;
}
err = fmctdc_flush(tdc, channel);
if (err)
return err;
err = config_and_acquire(tdc);
if (err) {
fprintf(stderr, "%s: Error: %s\n",
prog_name, fmctdc_strerror(errno));
return -1;
}
fmctdc_close(tdc);
return err;
}
static int config_and_acquire(struct fmctdc_board *tdc)
{
int err;
err = config(tdc);
if (err)
return err;
err = acquire(tdc);
if (err)
return err;
return err;
}
static int config(struct fmctdc_board *tdc)
{
int err = 0;
/* read-back */
int termination_rb;
int32_t offset_user_rb;
enum fmctdc_buffer_type buffer_type_rb;
enum fmctdc_buffer_mode buffer_mode_rb;
int buffer_len_rb;
int wr_mode_rb;
unsigned int coalescing_timeout_rb;
struct fmctdc_time time_rb;
err = fmctdc_set_termination(tdc, channel, termination);
if (err)
return err;
termination_rb = fmctdc_get_termination(tdc, channel);
if (termination_rb < 0)
return termination_rb;
assert(termination == termination_rb);
err = fmctdc_coalescing_timeout_set(tdc, channel, coalescing_timeout);
if (err)
return err;
err = fmctdc_get_coalescing_timeout(tdc, channel, &coalescing_timeout_rb);
if (err)
return err;
assert(coalescing_timeout == coalescing_timeout_rb);
err = fmctdc_wr_mode(tdc, wr_mode)
if (err)
return err;
wr_mode_rb = fmctdc_check_wr_mode(tdc);
if (wr_mode_rb < 0)
return wr_mode_rb;
assert(wr_mode == wr_mode_rb);
err = fmctdc_set_time(tdc, channel, time);
if (err)
return err;
err = fmctdc_get_time(tdc, channel, &time_rb);
if (err)
return err;
assert(time == time_rb);
err = fmctdc_set_offset_user(tdc, channel, offset_user);
if (err)
return err;
err = fmctdc_get_offset_user(tdc, channel, &offset_user_rb);
if (err)
return err;
assert(offset_user == offset_user_rb);
err = fmctdc_set_buffer_type(tdc, buffer_type);
if (err)
return err;
buffer_type_rb = fmctdc_get_buffer_type(tdc);
if (buffer_type_rb < 0)
return buffer_type_rb;
assert(buffer_type == buffer_type_rb);
err = fmctdc_set_buffer_len(tdc, channel, buffer_len);
if (err)
return err;
buffer_len_rb = fmctdc_get_buffer_len(tdc, channel);
if (buffer_len_rb < 0)
return buffer_len_rb;
assert(buffer_len == buffer_len_rb);
err = fmctdc_set_buffer_mode(tdc, channel, buffer_mode);
if (err)
return err;
buffer_mode_rb = fmctdc_get_buffer_mode(tdc, channel);
if (buffer_mode_rb < 0)
return buffer_mode_rb;
assert(buffer_mode == buffer_mode_rb);
return err;
}
static int acquire(struct fmctdc_board *tdc)
{
int err = 0;
err = fmctdc_channel_enable(tdc, channel);
if (err)
return err;
err = fetch_and_process(tdc);
if (err)
return err;
err = fmctdc_channel_disable(tdc, channel);
if (err)
return err;
return err;
}
static int fetch_and_process(struct fmctdc_board *tdc)
{
int err = 0;
int n, i;
float temperature;
const int max = 10;
struct fmctdc_time ts[max];
uint32_t recv, trans;
do {
n = fmctdc_read(tdc, channel, ts, max, O_NONBLOCK);
} while (n < 0 && errno == EAGAIN);
if (n < 0)
return n;
temperature = fmctdc_read_temperature(tdc);
err = fmctdc_stats_recv_get(tdc, channel, &recv);
if (err)
return err;
err = fmctdc_stats_trans_get(tdc, channel, &trans);
if (err)
return err;
printf("Temperature: %f\n", temperature);
printf("Stats: %d %d\n", recv, trans);
for (i = 0; i < n; ++i)
printf("Timestamp: "PRItsps"\n", PRItspsVAL(&ts[i]));
return err;
}
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