Commit eb2c3197 authored by Federico Vaga's avatar Federico Vaga

doc: update library API, use doxygen

Signed-off-by: Federico Vaga's avatarFederico Vaga <federico.vaga@cern.ch>
parent a48d211e
_build
.doxystamp
doxygen-fd-output
......@@ -18,4 +18,27 @@ help:
# "make mode" option. $(O) is meant as a shortcut for $(SPHINXOPTS).
%: Makefile
$(MAKE) -C drawings
$(MAKE) doxygen TARGET=$@
@$(SPHINXBUILD) -M $@ "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O)
GIT_VERSION = $(shell git describe --dirty --long --tags)
GIT_VERSION = $(shell git describe --dirty --long --tags)
doxygen:
ifeq ($(TARGET),clean)
@rm -rf doxygen-fd-output .doxystamp
else
$(MAKE) .doxystamp
endif
# List of Doxygen folders to consider
DOXINPUT := ../../lib
DOXINPUT += ../../kernel/fine-delay.h
DOXEXCL := ../../lib/PyFmcFineDelay
# List of actual Doxygen source files
DOXSRC = $(shell find $(DOXINPUT) -type f -name '*.[chS]')
.doxystamp: $(DOXSRC)
GIT_VERSION=$(GIT_VERSION) DOXINPUT="$(DOXINPUT)" DOXEXCL="$(DOXEXCL)" doxygen ./doxygen-fd-config
@touch .doxystamp
......@@ -28,6 +28,7 @@ author = 'Alessandro Rubini <rubini@gnudd.com>, Tomasz Wlostowski <Tomasz.Wlosto
# extensions coming with Sphinx (named 'sphinx.ext.*') or your custom
# ones.
extensions = [
'breathe',
]
# Add any paths that contain templates here, relative to this directory.
......@@ -53,3 +54,9 @@ html_theme = 'sphinx_rtd_theme'
# 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']
breathe_projects = {
"fine-delay": "doxygen-fd-output/xml/",
}
breathe_default_project = "fine-delay"
# SPDX-License-Identifier: CC0-1.0
#
# SPDX-FileCopyrightText: 2020 CERN
PROJECT_NAME = "Fmc Fine Delay"
PROJECT_NUMBER = $(GIT_VERSION)
PROJECT_BRIEF = "Fmc Fine Delay"
PROJECT_LOGO =
OUTPUT_DIRECTORY = doxygen-fd-output
CREATE_SUBDIRS = YES
TAB_SIZE = 8
OPTIMIZE_OUTPUT_FOR_C = YES
EXTRACT_STATIC = YES
CASE_SENSE_NAMES = YES
WARN_NO_PARAMDOC = YES
WARN_IF_UNDOCUMENTED = NO
INPUT = $(DOXINPUT)
RECURSIVE = YES
EXCLUDE = $(DOXEXCL)
GENERATE_HTML = NO
GENERATE_LATEX = NO
GENERATE_XML = YES
This diff is collapsed.
......@@ -71,8 +71,22 @@ enum fd_zattr_in_idx {
FD_ATTR_TDC__LAST,
};
/* Names have been chosen so that 0 is the default at load time */
/**
* TDC flag to disable input pulse detection
* When disabled time-stamping and delay are impossible
*/
#define FD_TDCF_DISABLE_INPUT 1
/**
* TDC flag to disable input pulse time-stamping
* When disabled time-stamping are impossible, but delay will work
*/
#define FD_TDCF_DISABLE_TSTAMP 2
/**
* TDC flag to enable a 50Ohm termination
*/
#define FD_TDCF_TERM_50 4
/* Output ZIO attributes */
......
......@@ -32,21 +32,29 @@ const char * const libfdelay_zio_version_s = "libfdelay is using zio version: "
#define ARRAY_SIZE(x) (sizeof(x) / sizeof((x)[0]))
/* Init the library: return the number of boards found */
/**
* Initialize the fdelay library. It must be called before doing
* anything else.
* @return 0 on success, otherwise -1 and errno is appropriately set
*/
int fdelay_init(void)
{
return 0;
}
/* Free and check */
/**
* Release the resources allocated by fdelay_init(). It must be called when
* you stop to use this library. Then, you cannot use functions from this
* library anymore.
*/
void fdelay_exit(void)
{
return ;
}
/**
* It opens one specific device. -1 arguments mean "not installed"
* @param[in] dev_id FMC device id. -1 to ignore it and use only the offset
* It opens one specific device.
* @param[in] dev_id Fine Delay device id.
* @return an instance token, otherwise NULL and errno is appripriately set.
* ENODEV if the device was not found. EINVAL there is a mismatch with
* the arguments
......@@ -110,30 +118,45 @@ err_stat_s:
return NULL;
}
/* Open one specific device by logical unit number (CERN/CO-like) */
struct fdelay_board *fdelay_open_by_lun(int lun)
{
ssize_t ret;
char dev_id_str[4];
char path_pattern[] = "/dev/fine-delay.%d";
char path[sizeof(path_pattern) + 1];
int dev_id;
if (fdelay_is_verbose())
fprintf(stderr, "called: %s(lun %i);\n", __func__, lun);
ret = snprintf(path, sizeof(path), path_pattern, lun);
if (ret < 0 || ret >= sizeof(path)) {
errno = EINVAL;
return NULL;
}
ret = readlink(path, dev_id_str, sizeof(dev_id_str));
if (sscanf(dev_id_str, "%4x", &dev_id) != 1) {
errno = ENODEV;
return NULL;
}
return fdelay_open(dev_id);
}
/**
* It opens one specific device using the logical unit number (CERN/CO-like)
* @param[in] lun Fine Delay LUN.
* @return an instance token, otherwise NULL and errno is appripriately set.
* ENODEV if the device was not found. EINVAL there is a mismatch with
* the arguments
*
* The function uses a symbolic link in /dev, created by the local
* installation procedure.
*/
struct fdelay_board *fdelay_open_by_lun(int lun)
{
ssize_t ret;
char dev_id_str[4];
char path_pattern[] = "/dev/fine-delay.%d";
char path[sizeof(path_pattern) + 1];
int dev_id;
if (fdelay_is_verbose())
fprintf(stderr, "called: %s(lun %i);\n", __func__, lun);
ret = snprintf(path, sizeof(path), path_pattern, lun);
if (ret < 0 || ret >= sizeof(path)) {
errno = EINVAL;
return NULL;
}
ret = readlink(path, dev_id_str, sizeof(dev_id_str));
if (sscanf(dev_id_str, "%4x", &dev_id) != 1) {
errno = ENODEV;
return NULL;
}
return fdelay_open(dev_id);
}
/**
* Close an FMC Fine Delay device opened with one of the following functions:
* fdelay_open(), fdelay_open_by_lun()
* @param[in] userb device token
* @return 0 on success, otherwise -1 and errno is appropriately set
*/
int fdelay_close(struct fdelay_board *userb)
{
struct __fdelay_board *b = (struct __fdelay_board *)userb;
......@@ -151,6 +174,13 @@ int fdelay_close(struct fdelay_board *userb)
}
/**
* Enable or disable White-Rabbit time
* @param[in] userb device token
* @param[in] on 1 to enable, 0 to disable
* @return 0 on success, otherwise an errno code.
* ENOTSUP when White-Rabbit is not supported
*/
int fdelay_wr_mode(struct fdelay_board *userb, int on)
{
__define_board(b, userb);
......@@ -160,6 +190,13 @@ int fdelay_wr_mode(struct fdelay_board *userb, int on)
return __fdelay_command(b, FD_CMD_WR_DISABLE);
}
/**
* Check White-Rabbit status
* @param[in] userb device token
* @return 0 if White-Rabbit is enabled, ENOTSUP when White-Rabbit is
* not supported, ENODEV if White-Rabbit is disabled, ENOLINK if the
* White-Rabbit link is down
*/
extern int fdelay_check_wr_mode(struct fdelay_board *userb)
{
__define_board(b, userb);
......@@ -168,6 +205,11 @@ extern int fdelay_check_wr_mode(struct fdelay_board *userb)
return errno;
}
/**
* Read the FMC Fine Delay temperature
* @param[in] userb device token
* @return temperature
*/
float fdelay_read_temperature(struct fdelay_board *userb)
{
uint32_t t;
......
......@@ -28,92 +28,110 @@ enum fmctdc_error_numbers {
__FDELAY_ERR_MAX,
};
/* Convenience macro for converting the physical output connector
numbers (as seen on the mezzanine's front panel) to convention used
by the drive (0..3). We keep 0..3 indexing to maintain library
compatibility. */
/**
* Convert the internal channel number to the one showed on the front-panel
*/
#define FDELAY_OUTPUT_HW_TO_USER(out) ((out) + 1)
#define FDELAY_OUTPUT_USER_TO_HW(out) ((out) - 1)
/* Opaque data type used as token */
struct fdelay_board;
struct fdelay_time {
uint64_t utc;
uint32_t coarse;
uint32_t frac;
uint32_t seq_id;
uint32_t channel;
};
/* The structure used for pulse generation */
struct fdelay_pulse {
/* FD_OUT_MODE_DISABLED, FD_OUT_MODE_DELAY, FD_OUT_MODE_PULSE */
int mode;
/* -1 == infinite */
int rep;
struct fdelay_time start;
struct fdelay_time end;
struct fdelay_time loop;
};
/* An alternative structure, internally converted to the previous one */
struct fdelay_pulse_ps {
int mode;
int rep;
struct fdelay_time start;
uint64_t length;
uint64_t period;
};
/*
* Please see the manual for the meaning of arguments and return values
/**
* Convert the channel number showed on the front-panel to the
* internal enumeration
*/
#define FDELAY_OUTPUT_USER_TO_HW(out) ((out) - 1)
extern int fdelay_init(void);
extern void fdelay_exit(void);
extern const char *fdelay_strerror(int err);
extern struct fdelay_board *fdelay_open(int dev_id);
extern struct fdelay_board *fdelay_open_by_lun(int lun);
extern int fdelay_close(struct fdelay_board *);
extern int fdelay_set_time(struct fdelay_board *b, struct fdelay_time *t);
extern int fdelay_get_time(struct fdelay_board *b, struct fdelay_time *t);
extern int fdelay_set_host_time(struct fdelay_board *b);
extern int fdelay_set_config_tdc(struct fdelay_board *b, int flags);
extern int fdelay_get_config_tdc(struct fdelay_board *b);
extern int fdelay_fread(struct fdelay_board *b, struct fdelay_time *t, int n);
extern int fdelay_fileno_tdc(struct fdelay_board *b);
extern int fdelay_read(struct fdelay_board *b, struct fdelay_time *t, int n,
int flags);
extern void fdelay_pico_to_time(uint64_t *pico, struct fdelay_time *time);
extern void fdelay_time_to_pico(struct fdelay_time *time, uint64_t *pico);
extern int fdelay_config_pulse(struct fdelay_board *b,
int channel, struct fdelay_pulse *pulse);
extern int fdelay_config_pulse_ps(struct fdelay_board *b,
int channel, struct fdelay_pulse_ps *ps);
extern int fdelay_has_triggered(struct fdelay_board *b, int channel);
extern int fdelay_wr_mode(struct fdelay_board *b, int on);
extern int fdelay_check_wr_mode(struct fdelay_board *b);
extern float fdelay_read_temperature(struct fdelay_board *b);
extern int fdelay_get_config_pulse(struct fdelay_board *userb,
int channel, struct fdelay_pulse *pulse);
extern int fdelay_get_config_pulse_ps(struct fdelay_board *userb,
int channel, struct fdelay_pulse_ps *ps);
/* libfmctdc version string */
extern const char * const libfdelay_version_s;
/* zio version string used during compilation of libfmctdc */
extern const char * const libfdelay_zio_version_s;
/**
* Opaque data type used as device token
*/
struct fdelay_board;
/**
* Time descriptor
*/
struct fdelay_time {
uint64_t utc; /**< seconds */
uint32_t coarse; /**< 8ns step (125MHz clock)*/
uint32_t frac; /**< coarse fractional part in 1.953125ps steps */
uint32_t seq_id; /**< time-stamp sequence number, used only by the TDC */
uint32_t channel; /**< channel number, used only by the TDC
as debug information */
};
/**
* The structure used for pulse generation
*/
struct fdelay_pulse {
int mode; /**< pulse mode must be one of the followings:
FD_OUT_MODE_DISABLED, FD_OUT_MODE_DELAY,
FD_OUT_MODE_PULSE */
int rep; /**< number of pulse repetitions,
maximum 65535 or 0 for infinite */
struct fdelay_time start; /**< rasising edge time */
struct fdelay_time end; /**< falling edge time */
struct fdelay_time loop; /**< period time */
};
/**
* The alternative structure used for pulse generation
* (internally converted to the previous one)
*/
struct fdelay_pulse_ps {
int mode; /**< pulse mode must be one of the followings:
FD_OUT_MODE_DISABLED, FD_OUT_MODE_DELAY,
FD_OUT_MODE_PULSE */
int rep; /**< number of pulse repetitions,
maximum 65535 or 0 for infinite */
struct fdelay_time start; /**< rasising edge time */
uint64_t length; /**< pulse width in pico-seconds */
uint64_t period; /**< pulse period in pico-seconds */
};
extern int fdelay_init(void);
extern void fdelay_exit(void);
extern const char *fdelay_strerror(int err);
extern struct fdelay_board *fdelay_open(int dev_id);
extern struct fdelay_board *fdelay_open_by_lun(int lun);
extern int fdelay_close(struct fdelay_board *);
extern int fdelay_set_time(struct fdelay_board *b, struct fdelay_time *t);
extern int fdelay_get_time(struct fdelay_board *b, struct fdelay_time *t);
extern int fdelay_set_host_time(struct fdelay_board *b);
extern int fdelay_set_config_tdc(struct fdelay_board *b, int flags);
extern int fdelay_get_config_tdc(struct fdelay_board *b);
extern int fdelay_fread(struct fdelay_board *b, struct fdelay_time *t, int n);
extern int fdelay_fileno_tdc(struct fdelay_board *b);
extern int fdelay_read(struct fdelay_board *b, struct fdelay_time *t, int n,
int flags);
extern void fdelay_pico_to_time(uint64_t *pico, struct fdelay_time *time);
extern void fdelay_time_to_pico(struct fdelay_time *time, uint64_t *pico);
extern int fdelay_config_pulse(struct fdelay_board *b,
int channel, struct fdelay_pulse *pulse);
extern int fdelay_config_pulse_ps(struct fdelay_board *b,
int channel, struct fdelay_pulse_ps *ps);
extern int fdelay_has_triggered(struct fdelay_board *b, int channel);
extern int fdelay_wr_mode(struct fdelay_board *b, int on);
extern int fdelay_check_wr_mode(struct fdelay_board *b);
extern float fdelay_read_temperature(struct fdelay_board *b);
extern int fdelay_get_config_pulse(struct fdelay_board *userb,
int channel, struct fdelay_pulse *pulse);
extern int fdelay_get_config_pulse_ps(struct fdelay_board *userb,
int channel, struct fdelay_pulse_ps *ps);
/**
* libfmctdc version string
*/
extern const char * const libfdelay_version_s;
/**
* zio version string used during compilation of libfmctdc
*/
extern const char * const libfdelay_zio_version_s;
#ifdef FDELAY_INTERNAL /* Libray users should ignore what follows */
#include <unistd.h>
......
......@@ -25,6 +25,11 @@
#define ARRAY_SIZE(x) (sizeof(x) / sizeof((x)[0]))
/**
* Convert pico-seconds into a `struct fdelay_time` data structure
* @param[in] pico pico-second to convert
* @param[out] time destination data structure
*/
void fdelay_pico_to_time(uint64_t *pico, struct fdelay_time *time)
{
uint64_t p = *pico;
......@@ -36,6 +41,11 @@ void fdelay_pico_to_time(uint64_t *pico, struct fdelay_time *time)
time->frac = p * 4096 / 8000;
}
/**
* Convert a `struct fdelay_time` data structure into pico-seconds
* @param[in] time time to convert
* @param[out] pico destination variable
*/
void fdelay_time_to_pico(struct fdelay_time *time, uint64_t *pico)
{
uint64_t p;
......@@ -66,6 +76,13 @@ static int __fdelay_get_ch_fd(struct __fdelay_board *b,
return 0;
}
/**
* Configure an FMC Fine Delay channel to produce a pulse
* @param[in] userb device token
* @param[in] channel channel number in range [0, 3] ([1,4] on the front-panel)
* @param[in] pulse pulse descriptor
* @return 0 on success, otherwise -1 and errno is appropriately set
*/
int fdelay_config_pulse(struct fdelay_board *userb,
int channel, struct fdelay_pulse *pulse)
{
......@@ -167,7 +184,16 @@ static void fdelay_add_signed_ps(struct fdelay_time *p, signed ps)
fdelay_sub_ps(p, -ps);
}
/* The "pulse_ps" function relies on the previous one */
/**
* Configure an FMC Fine Delay channel to produce a pulse
* @param[in] userb device token
* @param[in] channel channel number in range [0, 3] ([1,4] on the front-panel)
* @param[in] ps pulse descriptor
* @return 0 on success, otherwise -1 and errno is appropriately set
*
* This is a variant of fdelay_config_pulse() using a different pulse
* descriptor where pulse width and period are expressed in pico-seconds
*/
int fdelay_config_pulse_ps(struct fdelay_board *userb,
int channel, struct fdelay_pulse_ps *ps)
{
......@@ -182,6 +208,13 @@ int fdelay_config_pulse_ps(struct fdelay_board *userb,
return fdelay_config_pulse(userb, channel, &p);
}
/**
* Retrieve the current FMC Fine-Delay channel configuration
* @param[in] userb device token
* @param[in] channel channel number in range [0, 3] ([1,4] on the front-panel)
* @param[out] pulse pulse descriptor
* @return 0 on success, otherwise -1 and errno is appropriately set
*/
int fdelay_get_config_pulse(struct fdelay_board *userb,
int channel, struct fdelay_pulse *pulse)
{
......@@ -289,6 +322,16 @@ static void fdelay_subtract_ps(struct fdelay_time *t2,
*pico = (int64_t)pico2 - pico1;
}
/**
* Retrieve the current FMC Fine-Delay channel configuration
* @param[in] userb device token
* @param[in] channel channel number in range [0, 3] ([1,4] on the front-panel)
* @param[out] ps pulse descriptor
* @return 0 on success, otherwise -1 and errno is appropriately set
*
* This is a variant of fdelay_get_config_pulse() using a different pulse
* descriptor where pulse width and period are expressed in pico-seconds
*/
int fdelay_get_config_pulse_ps(struct fdelay_board *userb,
int channel, struct fdelay_pulse_ps *ps)
{
......@@ -307,6 +350,14 @@ int fdelay_get_config_pulse_ps(struct fdelay_board *userb,
return 0;
}
/**
* Retrieve the current FMC Fine-Delay channel configuration
* @param[in] userb device token
* @param[in] channel channel number in range [0, 3] ([1,4] on the front-panel)
* @return 1 if trigger did happen, 0 if trigget did not happen,
* otherwise -1 and errno is appropriately set
*/
int fdelay_has_triggered(struct fdelay_board *userb, int channel)
{
__define_board(b, userb);
......@@ -318,5 +369,3 @@ int fdelay_has_triggered(struct fdelay_board *userb, int channel)
return -1; /* errno already set */
return (mode & 0x80) != 0;
}
......@@ -29,6 +29,12 @@ static int config_mask =
FD_TDCF_DISABLE_TSTAMP |
FD_TDCF_TERM_50;
/**
* Configure TDC options
* @param[in] userb device token
* @param[in] flags is a bit-mask of FD_TDCF_* flags
* @return 0 on success, otherwise -1 and errno is appropriately set.
*/
int fdelay_set_config_tdc(struct fdelay_board *userb, int flags)
{
__define_board(b, userb);
......@@ -42,6 +48,12 @@ int fdelay_set_config_tdc(struct fdelay_board *userb, int flags)
return fdelay_sysfs_set(b, "fd-input/flags", &val);
}
/**
* Configure TDC options
* @param[in] userb device token
* @return on success, a bit-mask of FD_TDCF_* flags; otherwise -1 and errno
* is appropriately set.
*/
int fdelay_get_config_tdc(struct fdelay_board *userb)
{
__define_board(b, userb);
......@@ -63,6 +75,15 @@ static int __fdelay_open_tdc(struct __fdelay_board *b)
return b->fdc[0];
}
/**
* Get TDC file descriptor
* @param[in] userb device token
* @return on success, a valid file descriptor; otherwise -1 and errno
* is appropriately set.
*
* This returns the file descriptor associated to the TDC device,
* so you can *select* or *poll* before calling *fdelay_read*.
*/
int fdelay_fileno_tdc(struct fdelay_board *userb)
{
__define_board(b, userb);
......@@ -70,7 +91,16 @@ int fdelay_fileno_tdc(struct fdelay_board *userb)
}
/* "read" behaves like the system call and obeys O_NONBLOCK */
/**
* Read TDC timestamps
* @param[in] userb device token
* @param[out] t buffer for timestamps
* @param[in] n maximum number that t can store
* @param[in] flags for options: O_NONBLOCK for non blocking read
* @return the number of valid timestamps in the buffer, otherwise -1
* and errno is appropriately set. EAGAIN if the driver buffer is
* empty
*/
int fdelay_read(struct fdelay_board *userb, struct fdelay_time *t, int n,
int flags)
{
......@@ -122,7 +152,18 @@ int fdelay_read(struct fdelay_board *userb, struct fdelay_time *t, int n,
return i;
}
/* "fread" behaves like stdio: it reads all the samples */
/**
* Read TDC timestamps
* @param[in] userb device token
* @param[out] t buffer for timestamps
* @param[in] n maximum number that t can store
* @return the number of valid timestamps in the buffer, otherwise -1
* and errno is appropriately set.
*
* The function behaves like *fread*: it tries to read all samples,
* even if it implies sleeping several times. Use it only if you are
* aware that all the expected pulses will reach you.
*/
int fdelay_fread(struct fdelay_board *userb, struct fdelay_time *t, int n)
{
int i, loop;
......
......@@ -34,6 +34,14 @@ static char *names[] = {
"coarse"
};
/**
* Set board time
* @param[in] userb device token
* @param[in] t user time
* @return 0 on success, otherwise -1 and errno is appropriately set.
*
* It only uses the fields *utc* and *coarse*.
*/
int fdelay_set_time(struct fdelay_board *userb, struct fdelay_time *t)
{
__define_board(b, userb);
......@@ -50,6 +58,14 @@ int fdelay_set_time(struct fdelay_board *userb, struct fdelay_time *t)
return 0;
}
/**
* Get board time
* @param[in] userb device token
* @param[out] t board time
* @return 0 on success, otherwise -1 and errno is appropriately set.
*
* It only uses the fields *utc* and *coarse*.
*/
int fdelay_get_time(struct fdelay_board *userb, struct fdelay_time *t)
{
__define_board(b, userb);
......@@ -66,9 +82,18 @@ int fdelay_get_time(struct fdelay_board *userb, struct fdelay_time *t)
return 0;
}
/**
* Set board time to host time
* @param[in] userb device token
* @return 0 on success, otherwise -1 and errno is appropriately set.
*
* The precision should be in the order of 1 microsecond, but will drift over
* time. This function is only provided to coarsely correlate the board time
* with the system time. Relying on system time for synchronizing multiple
* *fine-delays* is strongly discouraged.
*/
int fdelay_set_host_time(struct fdelay_board *userb)
{
__define_board(b, userb);
return __fdelay_command(b, FD_CMD_HOST_TIME);
}
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