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 _build
.doxystamp
doxygen-fd-output
...@@ -18,4 +18,27 @@ help: ...@@ -18,4 +18,27 @@ help:
# "make mode" option. $(O) is meant as a shortcut for $(SPHINXOPTS). # "make mode" option. $(O) is meant as a shortcut for $(SPHINXOPTS).
%: Makefile %: Makefile
$(MAKE) -C drawings $(MAKE) -C drawings
$(MAKE) doxygen TARGET=$@
@$(SPHINXBUILD) -M $@ "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O) @$(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 ...@@ -28,6 +28,7 @@ author = 'Alessandro Rubini <rubini@gnudd.com>, Tomasz Wlostowski <Tomasz.Wlosto
# extensions coming with Sphinx (named 'sphinx.ext.*') or your custom # extensions coming with Sphinx (named 'sphinx.ext.*') or your custom
# ones. # ones.
extensions = [ extensions = [
'breathe',
] ]
# Add any paths that contain templates here, relative to this directory. # Add any paths that contain templates here, relative to this directory.
...@@ -53,3 +54,9 @@ html_theme = 'sphinx_rtd_theme' ...@@ -53,3 +54,9 @@ html_theme = 'sphinx_rtd_theme'
# relative to this directory. They are copied after the builtin static files, # relative to this directory. They are copied after the builtin static files,
# so a file named "default.css" will overwrite the builtin "default.css". # so a file named "default.css" will overwrite the builtin "default.css".
html_static_path = ['_static'] 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 { ...@@ -71,8 +71,22 @@ enum fd_zattr_in_idx {
FD_ATTR_TDC__LAST, FD_ATTR_TDC__LAST,
}; };
/* Names have been chosen so that 0 is the default at load time */ /* 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 #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 #define FD_TDCF_DISABLE_TSTAMP 2
/**
* TDC flag to enable a 50Ohm termination
*/
#define FD_TDCF_TERM_50 4 #define FD_TDCF_TERM_50 4
/* Output ZIO attributes */ /* Output ZIO attributes */
......
...@@ -32,21 +32,29 @@ const char * const libfdelay_zio_version_s = "libfdelay is using zio version: " ...@@ -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])) #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) int fdelay_init(void)
{ {
return 0; 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) void fdelay_exit(void)
{ {
return ; return ;
} }
/** /**
* It opens one specific device. -1 arguments mean "not installed" * It opens one specific device.
* @param[in] dev_id FMC device id. -1 to ignore it and use only the offset * @param[in] dev_id Fine Delay device id.
* @return an instance token, otherwise NULL and errno is appripriately set. * @return an instance token, otherwise NULL and errno is appripriately set.
* ENODEV if the device was not found. EINVAL there is a mismatch with * ENODEV if the device was not found. EINVAL there is a mismatch with
* the arguments * the arguments
...@@ -110,30 +118,45 @@ err_stat_s: ...@@ -110,30 +118,45 @@ err_stat_s:
return NULL; return NULL;
} }
/* Open one specific device by logical unit number (CERN/CO-like) */ /**
struct fdelay_board *fdelay_open_by_lun(int lun) * It opens one specific device using the logical unit number (CERN/CO-like)
{ * @param[in] lun Fine Delay LUN.
ssize_t ret; * @return an instance token, otherwise NULL and errno is appripriately set.
char dev_id_str[4]; * ENODEV if the device was not found. EINVAL there is a mismatch with
char path_pattern[] = "/dev/fine-delay.%d"; * the arguments
char path[sizeof(path_pattern) + 1]; *
int dev_id; * The function uses a symbolic link in /dev, created by the local
* installation procedure.
if (fdelay_is_verbose()) */
fprintf(stderr, "called: %s(lun %i);\n", __func__, lun); struct fdelay_board *fdelay_open_by_lun(int lun)
ret = snprintf(path, sizeof(path), path_pattern, lun); {
if (ret < 0 || ret >= sizeof(path)) { ssize_t ret;
errno = EINVAL; char dev_id_str[4];
return NULL; char path_pattern[] = "/dev/fine-delay.%d";
} char path[sizeof(path_pattern) + 1];
ret = readlink(path, dev_id_str, sizeof(dev_id_str)); int dev_id;
if (sscanf(dev_id_str, "%4x", &dev_id) != 1) {
errno = ENODEV; if (fdelay_is_verbose())
return NULL; fprintf(stderr, "called: %s(lun %i);\n", __func__, lun);
} ret = snprintf(path, sizeof(path), path_pattern, lun);
return fdelay_open(dev_id); 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) int fdelay_close(struct fdelay_board *userb)
{ {
struct __fdelay_board *b = (struct __fdelay_board *)userb; struct __fdelay_board *b = (struct __fdelay_board *)userb;
...@@ -151,6 +174,13 @@ int fdelay_close(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) int fdelay_wr_mode(struct fdelay_board *userb, int on)
{ {
__define_board(b, userb); __define_board(b, userb);
...@@ -160,6 +190,13 @@ int fdelay_wr_mode(struct fdelay_board *userb, int on) ...@@ -160,6 +190,13 @@ int fdelay_wr_mode(struct fdelay_board *userb, int on)
return __fdelay_command(b, FD_CMD_WR_DISABLE); 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) extern int fdelay_check_wr_mode(struct fdelay_board *userb)
{ {
__define_board(b, userb); __define_board(b, userb);
...@@ -168,6 +205,11 @@ extern int fdelay_check_wr_mode(struct fdelay_board *userb) ...@@ -168,6 +205,11 @@ extern int fdelay_check_wr_mode(struct fdelay_board *userb)
return errno; return errno;
} }
/**
* Read the FMC Fine Delay temperature
* @param[in] userb device token
* @return temperature
*/
float fdelay_read_temperature(struct fdelay_board *userb) float fdelay_read_temperature(struct fdelay_board *userb)
{ {
uint32_t t; uint32_t t;
......
...@@ -28,92 +28,110 @@ enum fmctdc_error_numbers { ...@@ -28,92 +28,110 @@ enum fmctdc_error_numbers {
__FDELAY_ERR_MAX, __FDELAY_ERR_MAX,
}; };
/* Convenience macro for converting the physical output connector /**
numbers (as seen on the mezzanine's front panel) to convention used * Convert the internal channel number to the one showed on the front-panel
by the drive (0..3). We keep 0..3 indexing to maintain library */
compatibility. */
#define FDELAY_OUTPUT_HW_TO_USER(out) ((out) + 1) #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 { * Convert the channel number showed on the front-panel to the
/* FD_OUT_MODE_DISABLED, FD_OUT_MODE_DELAY, FD_OUT_MODE_PULSE */ * internal enumeration
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
*/ */
#define FDELAY_OUTPUT_USER_TO_HW(out) ((out) - 1)
extern int fdelay_init(void); /**
extern void fdelay_exit(void); * Opaque data type used as device token
extern const char *fdelay_strerror(int err); */
struct fdelay_board;
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 *); * Time descriptor
*/
extern int fdelay_set_time(struct fdelay_board *b, struct fdelay_time *t); struct fdelay_time {
extern int fdelay_get_time(struct fdelay_board *b, struct fdelay_time *t); uint64_t utc; /**< seconds */
extern int fdelay_set_host_time(struct fdelay_board *b); uint32_t coarse; /**< 8ns step (125MHz clock)*/
uint32_t frac; /**< coarse fractional part in 1.953125ps steps */
extern int fdelay_set_config_tdc(struct fdelay_board *b, int flags); uint32_t seq_id; /**< time-stamp sequence number, used only by the TDC */
extern int fdelay_get_config_tdc(struct fdelay_board *b); uint32_t channel; /**< channel number, used only by the TDC
as debug information */
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); * The structure used for pulse generation
*/
extern void fdelay_pico_to_time(uint64_t *pico, struct fdelay_time *time); struct fdelay_pulse {
extern void fdelay_time_to_pico(struct fdelay_time *time, uint64_t *pico); int mode; /**< pulse mode must be one of the followings:
FD_OUT_MODE_DISABLED, FD_OUT_MODE_DELAY,
extern int fdelay_config_pulse(struct fdelay_board *b, FD_OUT_MODE_PULSE */
int channel, struct fdelay_pulse *pulse); int rep; /**< number of pulse repetitions,
extern int fdelay_config_pulse_ps(struct fdelay_board *b, maximum 65535 or 0 for infinite */
int channel, struct fdelay_pulse_ps *ps); struct fdelay_time start; /**< rasising edge time */
extern int fdelay_has_triggered(struct fdelay_board *b, int channel); struct fdelay_time end; /**< falling edge time */
struct fdelay_time loop; /**< period time */
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); * The alternative structure used for pulse generation
* (internally converted to the previous one)
extern int fdelay_get_config_pulse(struct fdelay_board *userb, */
int channel, struct fdelay_pulse *pulse); struct fdelay_pulse_ps {
extern int fdelay_get_config_pulse_ps(struct fdelay_board *userb, int mode; /**< pulse mode must be one of the followings:
int channel, struct fdelay_pulse_ps *ps); FD_OUT_MODE_DISABLED, FD_OUT_MODE_DELAY,
FD_OUT_MODE_PULSE */
/* libfmctdc version string */ int rep; /**< number of pulse repetitions,
extern const char * const libfdelay_version_s; maximum 65535 or 0 for infinite */
/* zio version string used during compilation of libfmctdc */ struct fdelay_time start; /**< rasising edge time */
extern const char * const libfdelay_zio_version_s; 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 */ #ifdef FDELAY_INTERNAL /* Libray users should ignore what follows */
#include <unistd.h> #include <unistd.h>
......
...@@ -25,6 +25,11 @@ ...@@ -25,6 +25,11 @@
#define ARRAY_SIZE(x) (sizeof(x) / sizeof((x)[0])) #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) void fdelay_pico_to_time(uint64_t *pico, struct fdelay_time *time)
{ {
uint64_t p = *pico; uint64_t p = *pico;
...@@ -36,6 +41,11 @@ void fdelay_pico_to_time(uint64_t *pico, struct fdelay_time *time) ...@@ -36,6 +41,11 @@ void fdelay_pico_to_time(uint64_t *pico, struct fdelay_time *time)
time->frac = p * 4096 / 8000; 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) void fdelay_time_to_pico(struct fdelay_time *time, uint64_t *pico)
{ {
uint64_t p; uint64_t p;
...@@ -66,6 +76,13 @@ static int __fdelay_get_ch_fd(struct __fdelay_board *b, ...@@ -66,6 +76,13 @@ static int __fdelay_get_ch_fd(struct __fdelay_board *b,
return 0; 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 fdelay_config_pulse(struct fdelay_board *userb,
int channel, struct fdelay_pulse *pulse) int channel, struct fdelay_pulse *pulse)
{ {
...@@ -167,7 +184,16 @@ static void fdelay_add_signed_ps(struct fdelay_time *p, signed ps) ...@@ -167,7 +184,16 @@ static void fdelay_add_signed_ps(struct fdelay_time *p, signed ps)
fdelay_sub_ps(p, -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 fdelay_config_pulse_ps(struct fdelay_board *userb,
int channel, struct fdelay_pulse_ps *ps) int channel, struct fdelay_pulse_ps *ps)
{ {
...@@ -182,6 +208,13 @@ int fdelay_config_pulse_ps(struct fdelay_board *userb, ...@@ -182,6 +208,13 @@ int fdelay_config_pulse_ps(struct fdelay_board *userb,
return fdelay_config_pulse(userb, channel, &p); 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 fdelay_get_config_pulse(struct fdelay_board *userb,
int channel, struct fdelay_pulse *pulse) int channel, struct fdelay_pulse *pulse)
{ {
...@@ -289,6 +322,16 @@ static void fdelay_subtract_ps(struct fdelay_time *t2, ...@@ -289,6 +322,16 @@ static void fdelay_subtract_ps(struct fdelay_time *t2,
*pico = (int64_t)pico2 - pico1; *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 fdelay_get_config_pulse_ps(struct fdelay_board *userb,
int channel, struct fdelay_pulse_ps *ps) int channel, struct fdelay_pulse_ps *ps)
{ {
...@@ -307,6 +350,14 @@ int fdelay_get_config_pulse_ps(struct fdelay_board *userb, ...@@ -307,6 +350,14 @@ int fdelay_get_config_pulse_ps(struct fdelay_board *userb,
return 0; 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) int fdelay_has_triggered(struct fdelay_board *userb, int channel)
{ {
__define_board(b, userb); __define_board(b, userb);
...@@ -318,5 +369,3 @@ int fdelay_has_triggered(struct fdelay_board *userb, int channel) ...@@ -318,5 +369,3 @@ int fdelay_has_triggered(struct fdelay_board *userb, int channel)
return -1; /* errno already set */ return -1; /* errno already set */
return (mode & 0x80) != 0; return (mode & 0x80) != 0;
} }
...@@ -29,6 +29,12 @@ static int config_mask = ...@@ -29,6 +29,12 @@ static int config_mask =
FD_TDCF_DISABLE_TSTAMP | FD_TDCF_DISABLE_TSTAMP |
FD_TDCF_TERM_50; 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) int fdelay_set_config_tdc(struct fdelay_board *userb, int flags)
{ {
__define_board(b, userb); __define_board(b, userb);
...@@ -42,6 +48,12 @@ int fdelay_set_config_tdc(struct fdelay_board *userb, int flags) ...@@ -42,6 +48,12 @@ int fdelay_set_config_tdc(struct fdelay_board *userb, int flags)
return fdelay_sysfs_set(b, "fd-input/flags", &val); 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) int fdelay_get_config_tdc(struct fdelay_board *userb)
{ {
__define_board(b, userb); __define_board(b, userb);
...@@ -63,6 +75,15 @@ static int __fdelay_open_tdc(struct __fdelay_board *b) ...@@ -63,6 +75,15 @@ static int __fdelay_open_tdc(struct __fdelay_board *b)
return b->fdc[0]; 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) int fdelay_fileno_tdc(struct fdelay_board *userb)
{ {
__define_board(b, userb); __define_board(b, userb);
...@@ -70,7 +91,16 @@ int fdelay_fileno_tdc(struct fdelay_board *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 fdelay_read(struct fdelay_board *userb, struct fdelay_time *t, int n,
int flags) int flags)
{ {
...@@ -122,7 +152,18 @@ int fdelay_read(struct fdelay_board *userb, struct fdelay_time *t, int n, ...@@ -122,7 +152,18 @@ int fdelay_read(struct fdelay_board *userb, struct fdelay_time *t, int n,
return i; 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 fdelay_fread(struct fdelay_board *userb, struct fdelay_time *t, int n)
{ {
int i, loop; int i, loop;
......
...@@ -34,6 +34,14 @@ static char *names[] = { ...@@ -34,6 +34,14 @@ static char *names[] = {
"coarse" "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) int fdelay_set_time(struct fdelay_board *userb, struct fdelay_time *t)
{ {
__define_board(b, userb); __define_board(b, userb);
...@@ -50,6 +58,14 @@ int fdelay_set_time(struct fdelay_board *userb, struct fdelay_time *t) ...@@ -50,6 +58,14 @@ int fdelay_set_time(struct fdelay_board *userb, struct fdelay_time *t)
return 0; 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) int fdelay_get_time(struct fdelay_board *userb, struct fdelay_time *t)
{ {
__define_board(b, userb); __define_board(b, userb);
...@@ -66,9 +82,18 @@ int fdelay_get_time(struct fdelay_board *userb, struct fdelay_time *t) ...@@ -66,9 +82,18 @@ int fdelay_get_time(struct fdelay_board *userb, struct fdelay_time *t)
return 0; 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) int fdelay_set_host_time(struct fdelay_board *userb)
{ {
__define_board(b, userb); __define_board(b, userb);
return __fdelay_command(b, FD_CMD_HOST_TIME); 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